ACdream 1415 Important Roads

Important Roads

Special JudgeTime Limit: 20000/10000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others)

Problem Description

The city where Georgie lives has n junctions some of which are connected by bidirectional roads.
      Every day Georgie drives from his home to work and back. But the roads in the city where Georgie lives are very bad, so they are very often closed for repair. Georgie noticed that when some roads are closed he still can get from home to work in the same time as if all roads were available.

But there are such roads that if they are closed for repair the time Georgie needs to get from home to work increases, and sometimes Georgie even cannot get to work by a car any more. Georgie calls such roads important.
      Help Georgie to find all important roads in the city.

Input

The first line of the input file contains n and m — the number of junctions and roads in the city where Georgie lives, respectively (2 ≤ n ≤ 20 000, 1 ≤ m ≤ 100 000). Georgie lives at the junction 1 and works at the junction n.

The following m lines contain information about roads. Each road is specified by the junctions it connects and the time Georgie needs to drive along it. The time to drive along the road is positive and doesn’t exceed 100 000. There can be several roads between a pair of junctions, but no road connects a junction to itself. It is guaranteed that if all roads are available, Georgie can get from home to work.

Output

Output l — the number of important roads — at the first line of the output file. The second line must contain l numbers, the numbers of important roads. Roads are numbered from 1 to m as they are given in the input file.

Sample Input

6 7
1 2 1
2 3 1
2 5 3
1 3 2
3 5 1
2 4 1
5 6 2

Sample Output

2
5 7

Source

Andrew Stankevich Contest 22

Manager

mathlover

解题:我觉得最有意思的是求割边,带有重边的求割边。。。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <climits>
  7 #include <vector>
  8 #include <queue>
  9 #include <cstdlib>
 10 #include <string>
 11 #include <set>
 12 #include <stack>
 13 #define LL long long
 14 #define pli pair<long long,int>
 15 #define INF 0x3f3f3f3f3f3fLL
 16 using namespace std;
 17 const int maxn = 20100;
 18 struct arc{
 19     int to,next;
 20     LL w;
 21     arc(int x = 0,LL y = 0,int z = -1){
 22         to = x;
 23         w = y;
 24         next = z;
 25     }
 26 };
 27 struct edge{
 28     int to,id,next;
 29     edge(int x = 0,int y = 0,int z = -1){
 30         to = x;
 31         id = y;
 32         next = z;
 33     }
 34 };
 35 arc e[maxn*20];
 36 edge g[maxn*20];
 37 int head[maxn],first[maxn],ans[maxn],tot2,num;
 38 int n,m,tot,x[maxn*20],y[maxn*20],z[maxn*20];
 39 int dfn[maxn],low[maxn],idx;
 40 LL d[2][maxn];
 41 void add(int u,int v,LL w){
 42     e[tot] = arc(v,w,head[u]);
 43     head[u] = tot++;
 44     e[tot] = arc(u,w,head[v]);
 45     head[v] = tot++;
 46 }
 47 void add2(int u,int v,int id){
 48     g[tot2] = edge(v,id,first[u]);
 49     first[u] = tot2++;
 50     g[tot2] = edge(u,id,first[v]);
 51     first[v] = tot2++;
 52 }
 53 void dijkstra(int s,LL ds[maxn]){
 54     priority_queue< pli,vector< pli >,greater< pli > >q;
 55     bool done[maxn] = {false};
 56     for(int i = 1; i <= n; i++) ds[i] = INF;
 57     ds[s] = 0;
 58     q.push(make_pair(ds[s],s));
 59     while(!q.empty()){
 60         int u = q.top().second;
 61         q.pop();
 62         if(done[u]) continue;
 63         done[u] = true;
 64         for(int i = head[u]; ~i; i = e[i].next){
 65             if(ds[e[i].to] > ds[u] + e[i].w){
 66                 ds[e[i].to] = ds[u] + e[i].w;
 67                 q.push(make_pair(ds[e[i].to],e[i].to));
 68             }
 69         }
 70     }
 71 }
 72 void tarjan(int u,int fa){
 73     dfn[u] = low[u] = ++idx;
 74     bool flag = true;
 75     for(int i = first[u]; ~i; i = g[i].next){
 76         if(g[i].to == fa && flag){
 77             flag = false;
 78             continue;
 79         }
 80         if(!dfn[g[i].to]){
 81             tarjan(g[i].to,u);
 82             low[u] = min(low[u],low[g[i].to]);
 83             if(low[g[i].to] > dfn[u]) ans[num++] = g[i].id;
 84         }else low[u] = min(low[u],dfn[g[i].to]);
 85     }
 86 }
 87 int main(){
 88     while(~scanf("%d %d",&n,&m)){
 89         memset(head,-1,sizeof(head));
 90         memset(first,-1,sizeof(first));
 91         memset(dfn,0,sizeof(dfn));
 92         memset(low,0,sizeof(low));
 93         idx = num = tot2 = tot = 0;
 94         for(int i = 1; i <= m; i++){
 95             scanf("%d %d %d",x+i,y+i,z+i);
 96             add(x[i],y[i],z[i]);
 97         }
 98         dijkstra(1,d[0]);
 99         dijkstra(n,d[1]);
100         LL tmp = d[0][n];
101         for(int i = 1; i <= m; i++){
102             int u = x[i];
103             int v = y[i];
104             if(d[0][u] + z[i] + d[1][v] == tmp || d[0][v] + z[i] + d[1][u] == tmp){
105                 add2(u,v,i);
106             }
107         }
108         for(int i = 1; i <= n; i++)
109             if(!dfn[i]) tarjan(i,-1);
110         printf("%d\n",num);
111         if(num){
112             for(int i = 0; i < num; i++)
113                 printf("%d%c",ans[i],i + 1 == num?‘\n‘:‘ ‘);
114         }
115     }
116     return 0;
117 }

时间: 2024-10-10 10:00:23

ACdream 1415 Important Roads的相关文章

Gym - 100338C Important Roads 最短路+tarjan

题意:给你一幅图,问有多少条路径使得去掉该条路后最短路发生变化. 思路:先起始两点求两遍单源最短路,利用s[u] + t[v] + G[u][v] = dis 找出所有最短路径,构造新图.在新图中找到所有的桥输出就可以了. 1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #inclu

codeforces Gym 100338C Important Roads

正反两次最短路用于判断边是不是最短路上的边,把最短路径上的边取出来.然后求割边. #include<bits/stdc++.h> using namespace std; typedef long long ll; #define fi first #define se second #define bug(x) cout<<#x<<'='<<x<<endl; #define FOR(i,s,e) for(int i = s; i < e;

ACdream 1415 最短路+桥

点击打开链接 题意:给个图,问你从1到n的最短路的路径上,有多少桥 思路:先是要满足条件最短路,然后判断每条边是不是最短路里的边,怎么判断也很简单,先从1开始求最短路和从n开始求最短路,对于边U到V来说,若1到U的最短路加上n到V的最短路在加上这条边的权值若等于1到n的最短路,那么这条边就是我们要的,就是这个条件if(dis1[U[i]]+COST[i]+dis2[V[i]]==maxdis||dis1[V[i]]+COST[i]+dis2[U[i]]==maxdis)maxdis是1到n的最短

Tarjan 联通图 Kuangbin 带你飞 联通图题目及部分联通图题目

Tarjan算法就不说了 想学看这 https://www.byvoid.com/blog/scc-tarjan/ https://www.byvoid.com/blog/biconnect/ 下面是几份基本的模版 首先是无向图割点桥的代码 下面的代码是用于求割点数目的 其中add_block[u] = x  表示删除u点之后增加的联通块个数.注意是增加的联通块个数 const int MAXN = 1010; const int MAXM = 10010; const int INF = 0x

ASC(22)C(最短路+双连通分量找桥或拓扑排序)

Important Roads Special JudgeTime Limit: 20000/10000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description The city where Georgie lives has n junctions some of which are connected by bidirectional r

双连通

poj 3352 Road Construction && poj 3177 Redundant Paths 给一个无向图,问最少需要添加多少条边,使它成为双连通图. 做法:边双连通缩点,成为一棵树.若要使得任意一棵树,变成一个双连通图,那么至少增加的边数 =(度数为1的结点数 + 1 )/ 2 1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 #include<cstdio

acdream1415(dij+优先队列+桥)

这题好坑,卡SPFA... 无奈只能用dij+优先队列了. 因为好久没有写过代码了,所以今天写dij时候突然觉得复杂度不对,dij+优先队列的复杂度是(n+m)logn,这种复杂度对于稠密图是非常慢!,而且还有超内存的可能(最坏情况要把n*n个点都存进优先队列),与我以前记得复杂度是nlogn不一样... 瞬间吓尿. 其实事实确实是这样,在采用斐波那契堆+dij时,斐波那契堆是插入复杂度为O(1),所以复杂度为nlogn+m,而普通我们用的STL种的priority_queue插入查询复杂度都是

【最短路】ACdream 1198 - Transformers&#39; Mission

Problem Description A group of transformers whose leader is Optimus Prime(擎天柱) were assigned a mission: to destroy all Decepticon's(霸天虎) bases. The bases are connected by roads. They must visit each base and place a bomb there. They start their missi

ACdream 1191(广搜)

题目链接:http://acdream.info/problem?pid=1191 Dragon Maze Time Limit: 2000/1000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description You are the prince of Dragon Kingdom and your kingdom is in danger o