3 3 1 2 7 2 3 4 3 1 4 3 2 1 2 7 2 3 4 0 0
-1 4
图的连通性问题~之求桥模板
#include "stdio.h" //本人觉得两点之间可能有多条边,这样的话,邻接矩阵就没法存了,转邻接表~ #include "string.h" #define N 1005 #define INF 0x3fffffff struct node { int x,y; int weight; int next; }edge[4*N*N]; int idx,head[N]; int set[N]; //并查集用 int root; bool mark[N],visit[N]; int low[N],dfn[N]; int stackk[4*N*N],num; int MIN(int a,int b){ return a<b?a:b; } void Init(){ idx=0; memset(head,-1,sizeof(head)); } int find(int x){ return set[x]==x?set[x]:set[x]=find(set[x]); } void Add(int x,int y,int weight) { edge[idx].x = x; edge[idx].y = y; edge[idx].weight = weight; edge[idx].next = head[x]; head[x] = idx++; } void Union(int x,int y) { int fa = find(x); int fb = find(y); if(fa!=fb) set[fa] = fb; } void DFS(int x,int times,int edge_father) { int i,y; int child=0; visit[x] = true; low[x] = dfn[x] = times; for(i=head[x]; i!=-1; i=edge[i].next) { y=edge[i].y; if(!visit[y]) { child++; DFS(y,times+1,i); low[x] = MIN(low[x],low[y]); //if(x==root && child==2) mark[root] = true; //记录顶点是否为割顶 //if(x!=root && low[y]>=dfn[x]) mark[x] = true; //记录顶点是否为割顶 if(low[y]>dfn[x]) stackk[num++] = i; //若边i为桥,存入stackk[]; } else if(edge_father!=-1 && i!=(edge_father^1)) //若当前边不为原来他father到他的边,更新low[x]; low[x] = MIN(low[x],dfn[y]); } } int solve(int n) { int i,ans = INF; num = 0; memset(visit,false,sizeof(visit)); //标记点是否已访问 //memset(mark,false,sizeof(mark)); root = 1; int times = 1; DFS(root,times,-1); for(i=0; i<num; ++i) ans = MIN(ans,edge[stackk[i]].weight); if(ans==INF) ans=-1; //不存在桥,ans=-1; if(ans==0) ans++; //如果桥权值是零,则最少要派一人去炸桥 return ans; } int main() { int i; int n,m; int x,y,k; while(scanf("%d %d",&n,&m),n&&m) { Init(); for(i=1; i<=n; ++i) set[i] = i; //并查集用 while(m--) { scanf("%d %d %d",&x,&y,&k); if(x==y) continue; Add(x,y,k); Add(y,x,k); Union(x,y); //合并两点 } bool flag = true; for(i=1; i<=n; ++i) //有一个点不连通,则flag为false; { if(find(i) != find(1)) flag = false; } if(!flag){ printf("0\n"); continue; } printf("%d\n",solve(n)); } return 0; }
#include "stdio.h" #include "string.h" #define N 1010 #define INF 0x3fffffff struct node { int x,y; bool visit; int weight; int next; }edge[2*N*N]; int idx,head[N]; int n,m; int time; int low[N],dfn[N]; bool mark[N]; int st[2*N*N],num; //存割边的编号 int MIN(int x,int y){ return x<y?x:y; } void Init(){idx=0; memset(head,-1,sizeof(head)); } void Add(int x,int y,int k) { edge[idx].x = x; edge[idx].y = y; edge[idx].visit = false; //该条边未被访问 edge[idx].weight = k; edge[idx].next = head[x]; head[x] = idx++; } int set[N]; int find(int x); void Union(int x,int y); void DFS(int x) { int i,y; low[x] = dfn[x] = ++time; for(i=head[x]; i!=-1; i=edge[i].next) { y = edge[i].y; if(edge[i].visit) continue; //该边已经访问过,continue; edge[i].visit = edge[i^1].visit = true; if(!dfn[y]) { DFS(y); low[x] = MIN(low[x],low[y]); if(low[y]>dfn[x]) st[num++] = i; } else low[x] = MIN(low[x],dfn[y]); } } int Solve() { int ans = INF; int i,j; time = 0; num = 0; memset(dfn,0,sizeof(dfn)); DFS(1); for(i=0; i<num; ++i) { if(ans>edge[st[i]].weight) ans = edge[st[i]].weight; } if(ans==INF) ans=-1; if(ans==0) ans=1; return ans; } int main() { bool flag; int i,j; int x,y,k; while(scanf("%d %d",&n,&m),n||m) { Init(); for(i=1; i<=n; ++i) set[i] = i; for(i=1; i<=m; ++i) { scanf("%d %d %d",&x,&y,&k); Add(x,y,k); Add(y,x,k); Union(x,y); } flag = true; for(i=1; i<=n; ++i) { if(find(i)!=find(1)) flag = false; } if(!flag) { printf("0\n"); continue; } //图不连通,派0个人去 printf("%d\n",Solve()); } return 0; } int find(int x) { return set[x]==x?set[x]:set[x]=find(set[x]); } void Union(int x,int y) { int fa = find(x); int fb = find(y); if(fa!=fb) set[fa] = fb; }