北极的猴子
Time Limit: 1000 MS Memory Limit: 256 MB
Submit Status
也许你不知道,在北极也有猴子,我们叫它们北极猴。北极猴们在北极一共有n个聚落,不妨叫它们1,2,…n号聚落;它们之间有m条双向道路(这意味着如果一条路从1号聚落到2号聚落,那么你可以过这条路从2号聚落到1号聚落),每条道路连接2个聚落,且拥有不同的长度。
不过,由于北极没有多少土地,所以它们之间经常为了争夺领土而开战,由此也产生了许多矛盾。这一天,猴子聚落s和猴子聚落t之间便宣布势不两立,北极联合猴协会调解无效后,它们要求摧毁m条道路中的一些路,使得这两个聚落不能互相到达。
猴子们觉得在北极摧毁道路是一件非常费力的事情,于是它们不希望摧毁两条以上的道路。不过,道路长短不一,所以猴子们希望摧毁的道路的总长度最小。
猴子毕竟只是猴子,它们不会算数,所以它们把选择道路的任务交给了你。
Input
第一行两个整数n,m(2≤ n ≤ 5000, 3 ≤ m ≤5000) 表示北极猴聚落的数量和双向道路的数量。
第二行两个不同的整数s,t ( 1≤ s,t ≤ n),表示势不两立的猴子聚落的编号。
接下来m行,每行三个整数x,y,z,( 1≤ x,y ≤ n, 1 ≤ z ≤ 109109 )表示从x到y有一条距离为z的双向道路。
Output
输出一个或两个整数,表示你选择的道路的编号。如果没有需要删除的道路,则输出0.
道路的编号按照输入顺序,记为1,2,…m.
如果输出两个整数,则它们应该不同,且较小的数在前。
如果有多组满足条件的答案,则输出字典序最小的答案。这意味着,如果答案是a,b,则优先选择a最小的答案;若还是有多组,选择b最小的答案。
如果找不到答案,输出-1.
Sample input and output
Sample Input | Sample Output |
---|---|
5 4 1 5 1 2 3 2 3 1 3 4 4 4 5 2 |
2 |
5 3 1 5 1 2 3 2 3 1 4 5 2 |
0 |
6 7 1 6 2 1 6 2 3 5 3 4 9 4 6 4 4 6 5 4 5 1 3 1 3 |
2 7 |
Hint
样例1:第二条道路的长度为1,且摧毁之后1号聚落和5号聚落不能互相到达。
Source
2018 UESTC ACM Training for Graph Theory
题解:让你找到一条或者两条边,去掉后是的s和t不再联通。如果找不到输出-1.如果有多个按字典序输出;很明显能看出用无向图的桥处理。
1.首先判断s和t是否相连,如果不相连,输出-1.
2.只去掉一条边,判断是否含有无向图的桥存在,如果存在,输出该边;
3.去掉两条边, 我们可以为每一条打上临时标记,然后可以转化为第2种情况;
4.如果去掉两条边也没有,则输出-1.
AC代码为:
#include<bits/stdc++.h> usingnamespace std; constint INF1=1e8; constint INF2=1e9; struct part{int to,W,net;} e[10010]; struct part1{int id,v;} pre[5010],pre1[5010]; int n,m,s,t,min1,min2,dfn[5010],low[5010],st[5010],cnt,num,cut[10010],vis[5010],flag[10010],h[5001][5001];void addedge(int x,int y,int z){ e[cnt].to=y; e[cnt].W=z; e[cnt].net=st[x]; st[x]=cnt++;}void findcut(int x,int f){ dfn[x]=low[x]=++num;for(int i=st[x];~i;i=e[i].net){if(!dfn[e[i].to]&&!flag[i]){ findcut(e[i].to,x); low[x]=min(low[x],low[e[i].to]);if(low[e[i].to]>dfn[x]&&h[x][e[i].to]==1){ cut[i]=1; cut[i^1]=1;}}elseif(e[i].to!=f &&!flag[i]) low[x]=min(low[x],dfn[e[i].to]);}}int bfs(int x,int y){ queue<int> q; memset(vis,0,sizeof(vis)); q.push(x); pre[x].v=x; vis[x]=1;int v=0;while(!q.empty()){int p=q.front(); q.pop();for(int i=st[p];~i;i=e[i].net){if(!vis[e[i].to]){ vis[e[i].to]=true; pre[e[i].to].v=p; pre[e[i].to].id=i; q.push(e[i].to);}if(e[i].to==y){ v=1;break;}}if(v==1)break;}int ans=-1;while(v==1&& y!=x){if(cut[pre[y].id]==1){if(e[pre[y].id].W<min1){ min1=e[pre[y].id].W; ans=pre[y].id/2+1;}elseif(e[pre[y].id].W==min1&&pre[y].id/2+1<ans) ans=pre[y].id/2+1;} y=pre[y].v;}if(v==0)return10000;elsereturn ans;}int bfs1(int x,int y){ memset(vis,0,sizeof(vis)); memset(pre1,-1,sizeof(pre1)); queue<int> q; pre1[x].v=x; q.push(x); vis[x]=true;int v=0;while(!q.empty()){int p=q.front(); q.pop();for(int i=st[p];~i;i=e[i].net){if(!vis[e[i].to]&& flag[i]==0){ vis[e[i].to]=true; pre1[e[i].to].v=p; pre1[e[i].to].id=i; q.push(e[i].to);}if(e[i].to==y && flag[i]==0){ v=1;break;}}if(v==1)break;}int ans=-1;while(v==1&& y!=x){if(cut[pre1[y].id]==1){if(e[pre1[y].id].W<min2){ min2=e[pre1[y].id].W; ans=pre1[y].id/2+1;}elseif(e[pre1[y].id].W==min2&&pre1[y].id/2+1<ans) ans=pre1[y].id/2+1;} y=pre1[y].v;}return ans;}int main(){ cnt=0; cin>>n>>m>>s>>t;int start=0;for(int i=0;i<=n+1;i++) st[i]=-1;int x,y,z;for(int i=1;i<=m;i++){ cin>>x>>y>>z; h[x][y]+=1; h[y][x]+=1; addedge(x,y,z); addedge(y,x,z); start=x;} memset(dfn,0,sizeof dfn); memset(low,0,sizeof low); num=0; findcut(s,0); min1=INF2;int ans=bfs(s,t);if(ans==10000){ printf("0 ");return(0);}int ans0=ans;int ans1=INF1,ans2=INF1;int tt=t,vv=0;int min3=INF2;while(tt!=s){ flag[pre[tt].id]=1; flag[pre[tt].id^1]=1; h[pre[tt].v][tt]-=1; h[tt][pre[tt].v]-=1; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(cut,0,sizeof(cut)); findcut(s,0); min2=INF2; ans=bfs1(s,t);if(ans!=-1){if(min2+e[pre[tt].id].W<min3){ min3=min2+e[pre[tt].id].W; ans1=pre[tt].id/2+1; ans2=ans;if(ans1>ans2) swap(ans1,ans2);}elseif(min2+e[pre[tt].id].W==min3){if(min(ans,pre[tt].id/2+1)<ans1){ ans1=min(pre[tt].id/2+1,ans); ans2=max(pre[tt].id/2+1,ans);}elseif(min(pre[tt].id/2+1,ans)==ans1 && max(ans,pre[tt].id/2+1)<ans2){ ans1=min(pre[tt].id/2+1,ans); ans2=max(pre[tt].id/2+1,ans);}if(ans1>ans2) swap(ans1,ans2);} vv=1;} flag[pre[tt].id]=0; flag[pre[tt].id^1]=0; h[pre[tt].v][tt]+=1; h[tt][pre[tt].v]+=1; tt=pre[tt].v;}if(ans0==-1){if(vv==0) cout<<-1<<endl;else cout<<min(ans1,ans2)<<" "<<max(ans1,ans2)<<endl;}else{if(vv==0) cout<<ans0<<endl;else{if(min1<min3) cout<<ans0<<endl;else cout<<min(ans1,ans2)<<" "<<max(ans1,ans2)<<endl;}}return0;}