重要道路
题目描述
给定一个无向图 G,对于其中的一条边(u,v),将它删除之后会使得从 1 到 n
的最短路长度增加,那么这条边被称为“重要道路”。
求 G 中所有的重要道路。
输入格式
第一行两个整数 n,m,分别代表点数和边数。
接下来 m 行,每行三个整数 u,v,c,代表权值为 c 的无向边(u,v)。可能有重
边,但没有自环。保证 1 号点和 n 号点是连通的。
输出格式
第一行一个整数 k,代表重要道路的数量。
下一行升序输出 k 个数代表重要道路的编号(按输入顺序从 1 到 m)。
输入样例
6 7
1 2 1
2 3 1
2 5 3
1 3 2
3 5 1
2 4 1
5 6 2
输出样例
2
5 7
数据规模
20%的数据,n,m<=10。
另外 20%的数据,m=n-1。
100%的数据,1<=n<=20000,1<=m,c<=100000。
SPFA求最短路
求出所有在最短路上的边
求出这些边的割边(桥)
此题卡SPFA,要用单调队列优化
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 struct Node 9 { 10 int next,to,dis,id; 11 }edge[400001]; 12 struct Edge 13 { 14 int u,v,w; 15 }e[200001]; 16 struct ZYYS 17 { 18 int x,d; 19 bool operator < (const ZYYS &a) 20 const 21 { 22 return d>a.d; 23 } 24 }; 25 int dist[200001],vis[200001],head[200001],num,ban[200001],n,m,d,ans,a[200001],dist2[200001]; 26 int dfn[200001],low[200001],cnt,instack[200001]; 27 void add(int u,int v,int dis,int id) 28 { 29 num++; 30 edge[num].next=head[u]; 31 head[u]=num; 32 edge[num].to=v; 33 edge[num].dis=dis; 34 edge[num].id=id; 35 } 36 void SPFA() 37 {int i; 38 priority_queue<ZYYS>Q; 39 for (i=1;i<=n;i++) 40 vis[i]=0,dist[i]=1e9; 41 dist[1]=0; 42 Q.push((ZYYS){1,0}); 43 while (Q.empty()==0) 44 { 45 ZYYS u=Q.top(); 46 Q.pop(); 47 vis[u.x]=0; 48 for (i=head[u.x];i;i=edge[i].next) 49 if (ban[i]==0) 50 { 51 int v=edge[i].to; 52 if (dist[v]>dist[u.x]+edge[i].dis) 53 { 54 dist[v]=dist[u.x]+edge[i].dis; 55 if (vis[v]==0) 56 { 57 vis[v]=1; 58 Q.push((ZYYS){v,dist[v]}); 59 } 60 } 61 } 62 } 63 } 64 void SPFA2() 65 {int i; 66 priority_queue<ZYYS>Q; 67 for (i=1;i<=n;i++) 68 dist2[i]=1e9,vis[i]=0; 69 dist2[n]=0; 70 Q.push((ZYYS){n,0}); 71 while (Q.empty()==0) 72 { 73 ZYYS u=Q.top(); 74 Q.pop(); 75 vis[u.x]=0; 76 for (i=head[u.x];i;i=edge[i].next) 77 if (ban[i]==0) 78 { 79 int v=edge[i].to; 80 if (dist2[v]>dist2[u.x]+edge[i].dis) 81 { 82 dist2[v]=dist2[u.x]+edge[i].dis; 83 if (vis[v]==0) 84 { 85 vis[v]=1; 86 Q.push((ZYYS){v,dist[v]}); 87 } 88 } 89 } 90 } 91 } 92 void dfs(int x,int pa) 93 {int flag=0,i; 94 dfn[x]=low[x]=++cnt; 95 instack[x]=1; 96 flag=0; 97 for (i=head[x];i;i=edge[i].next) 98 { 99 int v=edge[i].to; 100 if (flag==0&&v==pa) 101 { 102 flag=1;continue; 103 } 104 if (dfn[v]==0) 105 { 106 dfs(v,x); 107 low[x]=min(low[v],low[x]); 108 if (low[v]>dfn[x]) vis[edge[i].id]=1,ans++; 109 } 110 else if (instack[v]) low[x]=min(low[x],dfn[v]); 111 } 112 instack[x]=0; 113 } 114 int main() 115 {int i,u,v,w,j; 116 freopen("important.in","r",stdin); 117 freopen("important.out","w",stdout); 118 cin>>n>>m; 119 for (i=1;i<=m;i++) 120 { 121 scanf("%d%d%d",&u,&v,&w); 122 e[i].u=u,e[i].v=v,e[i].w=w; 123 add(u,v,w,i); 124 add(v,u,w,i); 125 } 126 SPFA(); 127 SPFA2(); 128 memset(vis,0,sizeof(vis)); 129 for (i=1;i<=n;i++) 130 { 131 for (j=head[i];j;j=edge[j].next) 132 { 133 int v=edge[j].to; 134 if (dist[i]+edge[j].dis+dist2[v]==dist[n]) 135 { 136 vis[(j+1)/2]=1; 137 } 138 } 139 } 140 memset(head,0,sizeof(head)); 141 num=0; 142 for (i=1;i<=m;i++) 143 if (vis[i]) add(e[i].u,e[i].v,e[i].w,i),add(e[i].v,e[i].u,e[i].w,i); 144 memset(vis,0,sizeof(vis)); 145 dfs(1,0); 146 cout<<ans<<endl; 147 for (i=1;i<=m;i++) 148 { 149 if (vis[i]) printf("%d ",i); 150 } 151 }