zoukankan      html  css  js  c++  java
  • loj2276 「HAOI2017」新型城市化

    给出的图是一个二分图(显然……吗),一个图的最大团=其补图的最大独立集,因此二分图的最大独立集就是补图的最大团。

    欲使补图最大团变大,则要最大独立集变大。二分图最大独立集=点数-最小点覆盖。最小点覆盖=最大匹配。

    即搞掉哪些边使得最大匹配变小。即二分图的必经边。

    二分图的必经边的判断:流量为 (1),且在残量网络上属于不同的强联通分量。

    (顺带一提,二分图的可行边:流量为 (1),或在残量网络上属于相同的强联通分量)

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    using namespace std;
    int n, m, hea[10005], cnt, uu[150005], vv[150005], col[10005], ss, tt, din, scc;
    int maxFlow, cur[10005], lev[10005], dfn[10005], loo[10005], idx, sta[10005], ans;
    int bel[10005];
    const int oo=0x3f3f3f3f;
    bool ins[10005];
    queue<int> d;
    vector<int> vec[10005];
    struct Edge{
    	int too, nxt, val;
    }edge[300005], odge[300005];
    void add_edge(int fro, int too, int val){
    	edge[cnt].nxt = hea[fro];
    	edge[cnt].too = too;
    	edge[cnt].val = val;
    	hea[fro] = cnt++;
    }
    void addEdge(int fro, int too, int val){
    	add_edge(fro, too, val);
    	add_edge(too, fro, 0);
    }
    void dfsColor(int x, int c){
    	col[x] = c;
    	for(int i=hea[x]; i!=-1; i=edge[i].nxt){
    		int t=edge[i].too;
    		if(!col[t])
    			dfsColor(t, c^1);
    	}
    }
    bool bfs(){
    	memset(lev, 0, sizeof(lev));
    	lev[ss] = 1;
    	d.push(ss);
    	while(!d.empty()){
    		int x=d.front();
    		d.pop();
    		for(int i=hea[x]; i!=-1; i=edge[i].nxt){
    			int t=edge[i].too;
    			if(!lev[t] && edge[i].val>0){
    				lev[t] = lev[x] + 1;
    				d.push(t);
    			}
    		}
    	}
    	return lev[tt]!=0;
    }
    int dfs(int x, int lim){
    	if(x==tt)	return lim;
    	int addFlow=0;
    	for(int &i=cur[x]; i!=-1; i=edge[i].nxt){
    		int t=edge[i].too;
    		if(lev[t]==lev[x]+1 && edge[i].val>0){
    			int tmp=dfs(t, min(lim-addFlow, edge[i].val));
    			edge[i].val -= tmp;
    			edge[i^1].val += tmp;
    			addFlow += tmp;
    			if(addFlow==lim)	break;
    		}
    	}
    	return addFlow;
    }
    void dinic(){
    	while(bfs()){
    		for(int i=ss; i<=tt; i++)	cur[i] = hea[i];
    		maxFlow += dfs(ss, oo);
    	}
    }
    void tarjan(int x){
    	dfn[x] = loo[x] = ++idx;
    	sta[++din] = x;
    	ins[x] = true;
    	for(int i=hea[x]; i!=-1; i=edge[i].nxt){
    		int t=edge[i].too;
    		if(edge[i].val==0)	continue;
    		if(!dfn[t]){
    			tarjan(t);
    			loo[x] = min(loo[x], loo[t]);
    		}
    		else if(ins[t])	loo[x] = min(loo[x], dfn[t]);
    	}
    	if(dfn[x]==loo[x]){
    		int j;
    		scc++;
    		do{
    			j = sta[din--];
    			ins[j] = false;
    			bel[j] = scc;
    		}while(dfn[j]!=loo[j]);
    	}
    }
    int main(){
    	memset(hea, -1, sizeof(hea));
    	cin>>n>>m;
    	for(int i=1; i<=m; i++){
    		scanf("%d %d", &uu[i], &vv[i]);
    		addEdge(uu[i], vv[i], 0);
    	}
    	for(int i=1; i<=n; i++)
    		if(!col[i])
    			dfsColor(i, 2);
    	cnt = 0;
    	memset(hea, -1, sizeof(hea));
    	for(int i=1; i<=m; i++){
    		if(col[uu[i]]<col[vv[i]])	addEdge(uu[i], vv[i], 1);
    		else	addEdge(vv[i], uu[i], 1);
    	}
    	ss = 0; tt = n + 1;
    	for(int i=1; i<=n; i++){
    		if(col[i]==2)	addEdge(ss, i, 1);
    		else	addEdge(i, tt, 1);
    	}
    	dinic();
    	for(int i=ss; i<=tt; i++)
    		if(!dfn[i])
    			tarjan(i);
    	for(int i=1; i<=n; i++)
    		if(col[i]==2){
    			for(int j=hea[i]; j!=-1; j=edge[j].nxt){
    				int t=edge[j].too;
    				if((j&1) || edge[j].val)	continue;
    				if(bel[i]!=bel[t]){
    					ans++;
    					if(t>i)	vec[i].push_back(t);
    					else	vec[t].push_back(i);
    				}
    			}
    		}
    	cout<<ans<<endl;
    	for(int i=1; i<=n; i++)
    		if(vec[i].size()){
    			sort(vec[i].begin(), vec[i].end());
    			for(int j=0; j<vec[i].size(); j++)
    				printf("%d %d
    ", i, vec[i][j]);
    		}
    	return 0;
    }
    
  • 相关阅读:
    MDX Step by Step 读书笔记(六) Building Complex Sets (复杂集合的处理) Filtering Sets
    在 Visual Studio 2012 开发 SSIS,SSAS,SSRS BI 项目
    微软BI 之SSIS 系列 在 SSIS 中读取 SharePoint List
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式) Infinite Recursion 和 SOLVE_ORDER 原理解析
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式)
    使用 SQL Server 2012 Analysis Services Tabular Mode 表格建模 图文教程
    MDX Step by Step 读书笔记(四) Working with Sets (使用集合) Limiting Set and AutoExists
    SQL Server 2012 Analysis Services Tabular Model 读书笔记
    Microsoft SQL Server 2008 MDX Step by Step 学习笔记连载目录
    2011新的开始,介绍一下AgileEAS.NET平台在新的一年中的发展方向
  • 原文地址:https://www.cnblogs.com/poorpool/p/8849275.html
Copyright © 2011-2022 走看看