Codeforces Gym 100338C Important Roads 最短路+Tarjan找桥
原题链接: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找桥的更多相关文章
- Gym - 100338C Important Roads 最短路+tarjan
题意:给你一幅图,问有多少条路径使得去掉该条路后最短路发生变化. 思路:先起始两点求两遍单源最短路,利用s[u] + t[v] + G[u][v] = dis 找出所有最短路径,构造新图.在新图中找到 ...
- codeforces Gym 100338C Important Roads (重建最短路图)
正反两次最短路用于判断边是不是最短路上的边,把最短路径上的边取出来建图.然后求割边.注意重边,和卡spfa. 正权,好好的dijkstra不用,用什么spfa? #include<bits/st ...
- Codeforces Gym 100338C C - Important Roads tarjan
C - Important RoadsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contes ...
- Tarjan找桥和割点与点连通分量与边连通分量【未成形】
之前只学了个强连通Tarjan算法,然后又摸了缩点操作: 然后今天在lightoj摸了一道模板题,是求所有桥的题: 然后发现,要把:割点,割点集合,双连通,最小割边集合(桥),点连通分量,边连通分量都 ...
- Codeforces.567E.President and Roads(最短路 Dijkstra)
题目链接 \(Description\) 给定一张有向图,求哪些边一定在最短路上.对于不一定在最短路上的边,输出最少需要将其边权改变多少,才能使其一定在最短路上(边权必须为正,若仍不行输出NO). \ ...
- Codeforces 160D Edges in MST tarjan找桥
Edges in MST 在用克鲁斯卡尔求MST的时候, 每个权值的边分为一类, 然后将每类的图建出来, 那些桥就是必须有的, 不是桥就不是必须有. #include<bits/stdc++.h ...
- Codeforces GYM 100876 J - Buying roads 题解
Codeforces GYM 100876 J - Buying roads 题解 才不是因为有了图床来测试一下呢,哼( 题意 给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得 ...
- Codeforces 806 D.Prishable Roads
Codeforces 806 D.Prishable Roads 题目大意:给出一张完全图,你需要选取其中的一些有向边,连成一个树形图,树形图中每个点的贡献是其到根节点路径上每一条边的边权最小值,现在 ...
- ACdream 1415 Important Roads
Important Roads Special JudgeTime Limit: 20000/10000MS (Java/Others)Memory Limit: 128000/64000KB (Ja ...
随机推荐
- Python语言程序设计之二--用turtle库画围棋棋盘和正、余弦函数图形
这篇笔记依然是在做<Python语言程序设计>第5章循环的习题.其中有两类问题需要记录下来. 第一是如何画围棋棋盘.围棋棋盘共有19纵19横.其中,位于(0,0)的星位叫天元,其余8个星位 ...
- ubuntu gcc的下载链接,比较快的。
http://mirrors.163.com/ubuntu-releases/ http://xhmikosr.1f0.de/tools/msys/
- ADT操作实例
ps.1.put(rank,value) 把当前rank的元素的数值修改 2.get(rank)获取rank的元素 3.remove(value)把向量中value剔除掉 4.size()返回元素个数 ...
- c++,友元类和友元函数
都是声明时友元的东西可以访问自己类的私有和保护成员 类的友元 友元是C++提供的一种破坏数据封装和数据隐藏的机制. 通过将一个模块声明为另一个模块的友元,一个模块能够引用到另一个模块中本是被隐藏的信息 ...
- MacOS常用软件推荐
1.效率提升神器Alfred 可以搜索文件.应用.web搜索.词典等等 链接:https://pan.baidu.com/s/1igv4tuXkuMFOPT9E6Cc5Jg 密码:3o51 软件解压密 ...
- 让 PHP COOKIE 立即生效(不用刷新就可以使用)
<?php function set_my_cookie($, $path = '', $domain = '') { $_COOKIE[$var] = $value; setcookie($v ...
- 浅析 Node.js 的 vm 模块以及运行不信任代码
在一些系统中,我们希望给用户提供插入自定义逻辑的能力,除了 RPC 和 REST 之外,运行客户提供的代码也是比较常用的方法,好处是可以极大地减少在网络上的耗时.JavaScript 是一种非常流行而 ...
- pycharm配置 自动运行指定脚本
配置:RUN -Debug Configuration Script: 脚本的地址 Script Parameters: 脚本的参数 Interpreter: python解释器
- koa2源码解读
最近在复习node的基础知识,于是看了看koa2的源码,写此文分享一下包括了Koa2的使用.中间件及上下文对象的大致实现原理. koa的github地址:https://github.com/koaj ...
- 【Luogu】P1169棋盘制作(单调栈)
题目链接 唉……这种题放在NOIP以前我是会做的……但是为什么现在反而不会了…… 单调栈.预处理每个点向上能扩展的最大距离,左右用两遍单调栈扫一遍.注意边界. #include<cstdio&g ...