原题链接:http://codeforces.com/gym/100338/attachments/download/2136/20062007-winter-petrozavodsk-camp-andrew-stankevich-contest-22-asc-22-en.pdf

题意

给你一个无向图,要从1走到n,问你哪些边去掉之后就没法走原本的最短路了。

题解

跑两发最短路,顺着跑一发,倒着跑一发,对于边(u,v),如果w(u,v)+d[u]+rd[v]或者w(u,v)+d[v]+rd[u]等于最短路,那么边(u,v)就是某条最短路上的边,将这些边标记好后,跑一发Tarjan找桥,这些桥就是答案。需要注意的是有重边。

代码

#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<set>
#define INF 21234567890
#define MAX_N 20004
#define MAX_M 112345
using namespace std; typedef long long ll; struct node {
public:
int u;
ll c; node(int uu, ll cc) : u(uu), c(cc) { } node() { } bool operator<(const node &a)const {
return c > a.c;
}
}; struct edge {
public:
int to;
ll cost;
bool isShort;
int id;
edge(int t, ll c,int i) : to(t), cost(c), isShort(), id(i){ } edge() { }
};
priority_queue<node> que;
int n, m; struct fuck {
public:
int u, v, c, id; fuck(int uu, int vv, int cc, int i) : u(uu), v(vv), c(cc), id(i) { } fuck() { }
bool operator<(const fuck &a)const{
if(a.u==u){
if(a.v==v)return a.c<c;
else return a.v<v;
}
return a.u<u;
}
}; set<fuck> se; vector<edge> G[MAX_N]; void dijkstra(int s,ll d[]) {
while (que.size())que.pop();
fill(d, d + n + , INF);
que.push(node(s, ));
d[s] = ;
while (que.size()) {
node now = que.top();
que.pop();
int u = now.u;
ll c = now.c;
if (d[u] < c)continue;
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i].to;
if (d[v] > d[u] + G[u][i].cost) {
d[v] = d[u] + G[u][i].cost;
que.push(node(v, d[v]));
}
}
}
} ll d[MAX_N],rd[MAX_N]; int father[MAX_N];
int dfn[MAX_N],low[MAX_N],ind=;
bool vis[MAX_N];
int sum=;
bool isBridge[MAX_M]; bool hasSame[MAX_M]; void Tarjan(int u,int p) {
father[u] = p;
dfn[u] = low[u] = ++ind;
vis[u] = ;
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i].to;
if (v == p||(!G[u][i].isShort))continue;
if (!vis[v]) {
Tarjan(v,u);
low[u] = min(low[u], low[v]);
if (low[v] > dfn[u]) {
sum++;
isBridge[G[u][i].id] = ;
}
}
else
low[u] = min(dfn[v], low[u]);
}
} bool ans[MAX_M]; int main() {
freopen("important.in", "r", stdin);
freopen("important.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = ; i < m; i++) {
int u, v;
int c;
scanf("%d%d%d", &u, &v, &c);
fuck f(u,v,c,i);
fuck f0(v,u,c,i);
auto it=se.find(f);
if(it!=se.end()){
hasSame[it->id]=;
continue;
}
it=se.find(f0);
if(it!=se.end()){
hasSame[it->id]=;
continue;
}
se.insert(f);
G[u].push_back(edge(v, c, i));
G[v].push_back(edge(u, c, i));
} dijkstra(, d);
dijkstra(n, rd);
ll sd = d[n];
for (int i = ; i <= n; i++)
for (int j = ; j < G[i].size(); j++) {
int u = i, v = G[i][j].to;
if (d[u] + rd[v] + G[i][j].cost == sd || d[v] + rd[u] + G[i][j].cost == sd)
G[i][j].isShort = ;
}
Tarjan(,);
int tot = ;
for (int i = ; i <= n; i++)
for (int j = ; j < G[i].size(); j++)
if (isBridge[G[i][j].id])
ans[G[i][j].id + ] = ;
for (int i = ; i <= m; i++)if ((!hasSame[i-])&&ans[i])tot++;
printf("%d\n", tot);
for (int i = ; i <= m; i++)
if (ans[i]&&(!hasSame[i-]))
printf("%d ", i);
printf("\n");
return ;
}

Codeforces Gym 100338C Important Roads 最短路+Tarjan找桥的更多相关文章

  1. Gym - 100338C Important Roads 最短路+tarjan

    题意:给你一幅图,问有多少条路径使得去掉该条路后最短路发生变化. 思路:先起始两点求两遍单源最短路,利用s[u] + t[v] + G[u][v] = dis 找出所有最短路径,构造新图.在新图中找到 ...

  2. codeforces Gym 100338C Important Roads (重建最短路图)

    正反两次最短路用于判断边是不是最短路上的边,把最短路径上的边取出来建图.然后求割边.注意重边,和卡spfa. 正权,好好的dijkstra不用,用什么spfa? #include<bits/st ...

  3. Codeforces Gym 100338C C - Important Roads tarjan

    C - Important RoadsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contes ...

  4. Tarjan找桥和割点与点连通分量与边连通分量【未成形】

    之前只学了个强连通Tarjan算法,然后又摸了缩点操作: 然后今天在lightoj摸了一道模板题,是求所有桥的题: 然后发现,要把:割点,割点集合,双连通,最小割边集合(桥),点连通分量,边连通分量都 ...

  5. Codeforces.567E.President and Roads(最短路 Dijkstra)

    题目链接 \(Description\) 给定一张有向图,求哪些边一定在最短路上.对于不一定在最短路上的边,输出最少需要将其边权改变多少,才能使其一定在最短路上(边权必须为正,若仍不行输出NO). \ ...

  6. Codeforces 160D Edges in MST tarjan找桥

    Edges in MST 在用克鲁斯卡尔求MST的时候, 每个权值的边分为一类, 然后将每类的图建出来, 那些桥就是必须有的, 不是桥就不是必须有. #include<bits/stdc++.h ...

  7. Codeforces GYM 100876 J - Buying roads 题解

    Codeforces GYM 100876 J - Buying roads 题解 才不是因为有了图床来测试一下呢,哼( 题意 给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得 ...

  8. Codeforces 806 D.Prishable Roads

    Codeforces 806 D.Prishable Roads 题目大意:给出一张完全图,你需要选取其中的一些有向边,连成一个树形图,树形图中每个点的贡献是其到根节点路径上每一条边的边权最小值,现在 ...

  9. ACdream 1415 Important Roads

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

随机推荐

  1. Linux下的硬件驱动——USB设备(转载)

    usb_bulk_msg函数 当对usb设备进行一次读或者写时,usb_bulk_msg 函数是非常有用的; 然而, 当你需要连续地对设备进行读/写时,建议你建立一个自己的urbs,同时将urbs 提 ...

  2. LeetCode(268) Missing Number

    题目 Given an array containing n distinct numbers taken from 0, 1, 2, -, n, find the one that is missi ...

  3. 线段树: CDOJ1598-加帕里公园的friends(区间合并,单点更新)

    加帕里公园的friends Time Limit: 3000/1000MS (Java/Others) Memory Limit: 131072/131072KB (Java/Others) 我还有很 ...

  4. Linux任务计划、周期性任务执行

    Linux任务计划.周期性任务执行 周期性任务执行: cron 守护进程(crond):服务,不间断地运行于后台 # service crond {start|stop|status|restart} ...

  5. Java技术——Java反射机制分析

    )生成动态代理. 2. Java反射API 反射API用来生成在当前Java虚拟机中的类.接口或者对象的信息. Class类:反射的核心类,可以获取类的属性,方法等内容信息. Field类:Java. ...

  6. python面试题解析(网络编程与并发)

    1.答: 应用层 与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的.例如,一个没有通信功能的字处理程序就不能执行通信的代码,从事字处理工作的程序员也不关心OSI的第7层.但是,如果添加了一 ...

  7. Andorid 生成NDK动态链接库 .so库

    .so库第一次见到是在搜索Android保存静态秘钥等特殊id字段做法时看到的-通过NDK的方式将静态秘钥保存在so文件中, 关于原生开发工具包(NDK)详细见官网指南要更详细,这里我记录我度娘各种结 ...

  8. 正则表达式 去除所有非ASCII字符

    需求: 去除字符串中包含的所有外国字符 只能使用正则如下,找到包含非ASCII的记录 db=# select * from test where info ~ '[^(\x00-\x7f)]'; id ...

  9. JS数组的下标如果是字符串的排序

    var test = []; test['0'] = 0; test['1'] = 1; test['2'] = 2; 这样一个数组的排序方式是字符为‘1’的数组元素排第一,为‘0’的排在最后

  10. List容器——LinkedList及常用API,实现栈和队列

    LinkedList及常用API ①   LinkedList----链表 ②   LinkedList类扩展AbstractSequentialList并实现List接口 ③   LinkedLis ...