標籤:
大意:有n座島和m條橋,每條橋上有w個兵守著,現在要派不少於守橋計程車兵數的人去炸橋,只能炸一條橋,使得這n座島不連通,求最少要派多少人去。
思路:我們就是要縮點後直接求橋上人的最少數量。(PS:1、注意圖如果不聯通直接輸出0。2、如果圖中的橋上人為0,個那麼要讓一個人去。3、重邊的問題。這裡可以忽略)
#include<map>#include<queue>#include<cmath>#include<cstdio>#include<stack>#include<iostream>#include<cstring>#include<algorithm>#define LL int#define inf 0x3f3f3f3f#define eps 1e-8#include<vector>#define ls l,mid,rt<<1#define rs mid+1,r,rt<<1|1using namespace std;const int Ma = 1100;struct node{ int to,w,next;}q[Ma*Ma];int head[Ma*Ma],dfn[Ma],num[Ma],du[Ma],stk[Ma*5],vis[Ma],low[Ma];int cnt,top,tim,scc,out[Ma],f[Ma],n,mi;void Add(int a,int b,int c){ q[cnt].to = b; q[cnt].w = c; q[cnt].next = head[a]; head[a] = cnt++;}void init(){ scc = cnt = top = 0; tim = 1; mi = inf; memset(head,-1,sizeof(head)); for(int i = 1;i <= n;++ i){ f[i] = i; low[i] = vis[i] = out[i] = num[i] = dfn[i] = 0; }}void Tarjan(int u,int To){ low[u] = dfn[u] = tim++; vis[u] = 1; stk[top++] = u; for(int i = head[u]; ~i ; i = q[i].next){ int v = q[i].to; if(i == (To^1)) continue; if(!vis[v]){ Tarjan(v,i); low[u] = min(low[u],low[v]); if(low[v] > dfn[u]) if(q[i].w < mi) mi = q[i].w; } else low[u] = min(low[u],dfn[v]); } if(low[u] == dfn[u]){ scc++; while(top > 0&&stk[top] != u){ top --; vis[stk[top] ] = 1; num[stk[top] ] = scc; } }}int fi(int x){ return f[x] == x ? x:f[x]=fi(f[x]);}void mer(int a,int b){ int x = fi(a); int y = fi(b); x > y ? f[x] = y:f[y] = x;}int main(){ int m,i,j,k,a,b,c,cla; while(~scanf("%d%d",&n,&m)){ if(!n&&!m) break; init(); for(i = 0;i < m;++ i){ scanf("%d%d%d",&a,&b,&c); Add(a,b,c); Add(b,a,c); mer(a,b); } int tmp = 0; for(i = 1;i <= n;++ i) if(f[i] == i){ tmp++; if(tmp > 1) break; } if(tmp > 1){ puts("0");continue; } Tarjan(1,-1); for(i = 1;i <= n;++ i){ for(j = head[i]; ~j ; j=q[j].next){ int v = q[j].to; if(num[i]!=num[v]){ out[num[i]]++; } } } int ans = 0; for(i = 1;i <= scc;++ i){ if(out[i]==0) ans++; } if(ans==1){ puts("-1"); } else if(!mi){ puts("1"); } else printf("%d\n",mi); } return 0;}
HDU 4738 Caocao's Bridges(雙聯通分量+並查集)