思路:先找到1到n的所有最短路径上的边,然后在这些边中间找边双连通桥即为答案。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<set> #include<stack> #define maxn 1<<29 using namespace std; struct edge { int from,to; long long len; }; struct ed { int u,v; }; struct node { int ve; long long dis; }; vector<edge>edges; stack<int>st; vector<int>g[22222]; set<int>s[22222]; set<int>ss[22222]; int pre[22222]; bool bb[222222]; int num; bool vis[22222]; long long dis[22222]; vector<int>ans; bool inst[22222]; int dfn[22222],low[22222]; int n,m; void add(int from,int to,long long len) { edges.push_back((edge){from,to,len}); g[from].push_back(edges.size()-1); } struct cmp { bool operator()(node &x,node &y) { return x.dis>y.dis; } }; void tarjan(int u) { dfn[u]=low[u]=++num; st.push(u); inst[u]=1; //int size=s[u].size(); set<int>::iterator it; for(it=ss[u].begin();it!=ss[u].end();it++) //for(int i=0;i<size;i++) { if(bb[*it])continue; bb[*it]=bb[(*it)^1]=1; edge e=edges[*it]; if(!dfn[e.to]) { tarjan(e.to); low[u]=min(low[u],low[e.to]); if(low[e.to]>dfn[u]) { ans.push_back((*it)/2+1); } } else if(inst[e.to]) { low[u]=min(low[u],dfn[e.to]); } } int v; if(dfn[u]==low[u]) do { v=st.top(); st.pop(); inst[v]=0; }while(u!=v); } void solve() { priority_queue<node,vector<node>,cmp>q; memset(pre,0,sizeof(pre)); for(int i=1;i<=n;i++)dis[i]=-1; //for(int i=1;i<=n;i++)cout<<dis[i]<<endl; dis[1]=0; node temp; temp.ve=1; temp.dis=0; q.push(temp); while(!q.empty()) { //cout<<1<<endl; node a=q.top(); q.pop(); if(vis[a.ve])continue; else { int u=a.ve; vis[u]=1; int size=g[u].size(); for(int i=0;i<size;i++) { edge e=edges[g[u][i]]; int v=e.to; int dd=e.len; if(dis[u]+dd==dis[v]&&dis[v]!=-1) { s[v].insert(g[u][i]^1); } else if(dis[u]+dd<dis[v]||dis[v]==-1) { s[v].clear(); s[v].insert(g[u][i]^1); dis[v]=dis[u]+dd; pre[v]=g[u][i]; temp.ve=v; temp.dis=dis[v]; q.push(temp); } //cout<<dis[v]<<endl; } } } queue<int>qq; memset(vis,0,sizeof(vis)); qq.push(n); vis[n]=1; while(!qq.empty()) { int u=qq.front(); qq.pop(); set<int>::iterator it; for(it=s[u].begin();it!=s[u].end();it++) { edge e=edges[*it]; ss[u].insert(*it); ss[e.to].insert((*it)^1); if(!vis[e.to]) { qq.push(e.to); vis[e.to]=1; } } } // for(int i=1;i<=n;i++) // { // //int size=s[i].size(); // set<int>::iterator it; // for(it=s[i].begin();it!=s[i].end();it++) // //for(int j=0;j<size;j++) // { // //cout<<(*it)<<endl; // edge e=edges[*it]; // s[e.to].insert((*it)^1); // } // } memset(dfn,0,sizeof(dfn)); for(int i=1;i<=n;i++) { if(!dfn[i])tarjan(i); } printf("%d\n",ans.size()); for(int i=0;i<ans.size();i++) { if(i==0)printf("%d",ans[i]); else printf(" %d",ans[i]); } printf("\n"); } int main() { int u,v; long long l; scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%lld",&u,&v,&l); add(u,v,l); add(v,u,l); } num=0; solve(); return 0; }