lgP3731 [HAOI2017]新型城市化

题意:有多少条,一定被包含在最大匹配里面

sol.

60分,断掉每一条边,看是否任然满流,若不满流,则必须出现在最大匹配里面

考虑满分做法

直接如果一条边,在残余网络的一个强连通分量里面,是可以不选的

就做完了

#include<bits/stdc++.h>
#define MAXN 10005
#define MAXM 200005
#define INF 0x3f3f3f3f
using namespace std;

int n,m;
int color[MAXN],vis[MAXN],S,T;
vector<int>G[MAXN];
int h[MAXN],tot,G1[MAXM],G2[MAXM];


int le,ans_yl;
pair<int , int> t[MAXN];

struct node{int from,to,next,rest;}e[MAXM << 1];
void add(int x , int y , int z){
	tot++;
	e[tot].from = x;
	e[tot].to = y;
	e[tot].rest = z;
	e[tot].next = h[x];
	h[x] = tot;
}

bool cmp(pair<int , int> A , pair<int , int> B){
	if(A.first == B.first)return A.second < B.second;
	return A.first < B.first;
}

int dis[MAXN];
queue<int>q;
bool bfs(){
	memset(vis , 0 , sizeof(vis));
	memset(dis , 0x3f , sizeof(dis));
	while(!q.empty())q.pop();q.push(S) , dis[S] = 0 , vis[S] = 1;int now;
	while(!q.empty()){
		now = q.front() , q.pop() , vis[now] = 0;
		for(int i = h[now] ; i != (-1) ; i = e[i].next){
			if(!e[i].rest)continue;
			if(dis[e[i].to] <= dis[now] + 1)continue;
			dis[e[i].to] = dis[now] + 1; 
			if(!vis[e[i].to])vis[e[i].to] = 1 , q.push(e[i].to);
		}
	}
	return (dis[T] < INF);
}

int dfs(int now , int low){
	if(now == T)return low;
	int used = low , res;
	for(int i = h[now] ; i != (-1) ; i = e[i].next){
		if(!e[i].rest)continue;
		if(dis[e[i].to] != dis[now] + 1)continue;
		if(res = dfs(e[i].to , min(used , e[i].rest))){
			used -= res;
			e[i].rest -= res;
			e[i ^ 1].rest += res;
			if(!used)break;
		}
	}
	return low - used;
}

int dinic(){
	int zz = 0;
	while(bfs()){
		zz = zz + dfs(S , INF);
	}
	return zz;
}

int init(int dx){
	memset(h , -1 , sizeof(h)) , tot = (-1);
	int x,y;
	for(int i = 1 ; i <= m ; i++){
		if(i == dx)continue;
		if(color[G1[i]] == 1)swap(G1[i] , G2[i]);
		x = G1[i] , y = G2[i];
		add(x , y , 1) , add(y , x , 0);
	}
	for(int i = 1 ; i <= n ; i++){
		if(color[i] == 0)add(S , i , 1) , add(i , S , 0);
		else add(i , T , 1) , add(T , i , 0);
	}
	return dinic();	
	
}

void ycl(int now , int fa){
	vis[now] = 1;
	for(auto v : G[now]){
		if(v == fa)continue;
		if(vis[v])continue;
		color[v] = color[now] ^ 1;
		ycl(v , now);
	}
}

int low[MAXN],dfn[MAXN],dex,belong[MAXN],js;

stack<int>q2;

void tarjan(int now , int fa){
	low[now] = dfn[now] = ++dex , vis[now] = 1;
	q2.push(now);
	for(int i = h[now] ; i != (-1) ; i = e[i].next){
		if(e[i].to == fa)continue;
		if(!e[i].rest)continue;
		if(!dfn[e[i].to]){
			tarjan(e[i].to , now);
			low[now] = min(low[now] , low[e[i].to]);
		}
		else if(!belong[e[i].to])low[now] = min(low[now] , dfn[e[i].to]);
	}
	if(dfn[now] == low[now]){
		int u;js++;
		do{
			u = q2.top() , q2.pop() , vis[u] = 0;
			belong[u] = js;
		}while(u != now);
	}
}

int main(){
	scanf("%d%d" , &n , &m) , S = 0 , T = n + 1;
	for(int i = 1 ; i <= m ; i++)scanf("%d%d" , &G1[i] , &G2[i]) , G[G1[i]].push_back(G2[i]) , G[G2[i]].push_back(G1[i]);
	for(int i = 1 ; i <= n ; i++)if(!vis[i])ycl(i , i);
	ans_yl = init(0);
	
	memset(vis , 0 , sizeof(vis));
	for(int i = S ; i <= T ; i++){
		if(!dfn[i])tarjan(i , i);
	}
	
	
	for(int i = 0 ; i <= tot ; i = i + 2){
		if(e[i].from == S || e[i].to == S)continue;
		if(e[i].from == T || e[i].to == T)continue;
		if(e[i].rest)continue;
		if(belong[e[i].from] == belong[e[i].to])continue;
		le++ , t[le].first = e[i].from , t[le].second = e[i].to;
		if(t[le].first > t[le].second)swap(t[le].first , t[le].second);
	}
	
	sort(t + 1 , t + 1 + le , cmp);
	cout<<le<<endl;
	for(int i = 1 ; i <= le ; i++){
		cout<<t[i].first<<" "<<t[i].second<<endl;
	}
	
	
	
	
}
上一篇:android用户界面-组件Widget-列表视图ListView


下一篇:手写防抖函数debounce和节流函数throttle