20160928的考试】图论(网络流,网络流,图论乱搞)

T1 二分图匹配 ,手贱匈牙利dfs写错了

T2 网络流   惨啊…………dinic手癌写错了,在往后增广的时候……应该用当前剩余流量……我敲成了在这个节点的所有流量……瞬间爆炸

//====================================================================================================================

T3 题意:定义两个有向图相似,当且仅当这两个图内任意两点间连通性相同(对于任意i,j∈V,如果原图i可以到达j,相似的图中i也可以到达j)。 给定一个有向图,求与它相似的图的最小边数和最大边数(没有重边和自环)(点数<=1000)


考虑若点集S(|S|>1)强连通,则边数最少时S为一个环(边数=|S|),边数最多时S为一个团(边数=|S|*(|S|-1))

缩了点后重新标号,新的图为一个DAG。显然求最大边数时可以直接把当前点能到达的所有点都连上边,随便搞搞就好了;而最小边数需要再瞎瘠薄搞一搞


对于求最小边数,原题简化为对于一个DAG,删掉尽量多的边使原图连通性不改变。

若有形如下图的结构,显然边(1,3)可以删去,

                  ①---→②-----→③

                   └--------------↗

观察得,若可以删去边(i,j),当且仅当 【对于任意点 j 可以抵达的点 ,点 i 都可以在不经过边(i,j)的情况下到达】时。

记录可达性的话……直接用bitset压一下就好

目测得,应该尽量走最长路,所以把点按照【和 i 的距离】升序枚举一遍即可(可以预先拓扑排序一下)……正确性……感性理解【捂脸.gif】


三次才A,代码准确率有待提高

一周目30’:枚举时now写成了 i

二周目60‘:建新图直接用的邻接矩阵,虽然保证了原图没有重边,但缩点后的图很容易出现重边,于是如果用0..1的邻接矩阵来记录……入度出度可能会出事……

三周目AC,代码↓

#include
#define MAXN 1005
#define MAXM 100005
using namespace std;	int n,m;
struct t1{
	int to,nxt;
}edge[MAXM];	int cnt_edge=0;
int fst[MAXN];
void addedge(int x,int y){
	edge[++cnt_edge].to=y;
	edge[cnt_edge].nxt=fst[x];
	fst[x]=cnt_edge;
}

int col[MAXN],cnt_col;
int siz[MAXN];
int stk[MAXN],top=0;
int vis[MAXN],in_stk[MAXN];
int low[MAXN],dfn[MAXN],cnt_dfs=0;
void tarjan(int now){
	vis[now]=in_stk[now]=1;
	dfn[now]=low[now]=++cnt_dfs;
	stk[++top]=now;

	for(int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
		int aim=edge[tmp].to;
		if(!dfn[aim])	tarjan(aim),low[now]=min(low[now],low[aim]);
		else{
			if(in_stk[aim])	low[now]=min(low[now],dfn[aim]);
		}
	}
	
	if(dfn[now]==low[now]){
		++cnt_col;
		for(;stk[top]^now;--top)
			col[stk[top]]=cnt_col,in_stk[stk[top]]=0,++siz[cnt_col];
		col[now]=cnt_col,in_stk[now]=0,--top,++siz[cnt_col];
	}
}

int re_grp[MAXN][MAXN];
int ind[MAXN],oud[MAXN],dis[MAXN];
int que[MAXN],head,tail;
bitset reach[MAXN];
int cnt[MAXN];

void re_build(){
	for(int now=1;now<=n;++now){
		for(int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
			int aim=edge[tmp].to;
			if(col[aim]^col[now]&&!re_grp[col[now]][col[aim]])
				re_grp[col[now]][col[aim]]=1,++ind[col[aim]],++oud[col[now]];
		}
	}
	head=tail=0;
	for(int i=1;i<=cnt_col;++i)	if(!oud[i])	que[tail++]=i,dis[i]=1;
	while(head^tail){
		int now=que[head++];
		for(int i=1;i<=cnt_col;++i){
			if(re_grp[i][now]){
				--oud[i];
				if(oud[i]==0)	que[tail++]=i,dis[i]=dis[now]+1;
			}
		}
	}
}

void work1(){
	int ans=0;
	for(int i=0;i1)	ans+=siz[i];
	printf("%d ",ans);
}

void work2(){
	int ans=0;
	for(int i=0;i


你可能感兴趣的:(网络流,OI,TEST,图论,tarjan)