原题链接: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. pandas处理较大数据量级的方法 - chunk,hdf,pkl

    前情提要: 工作原因需要处理一批约30G左右的CSV数据,数据量级不需要hadoop的使用,同时由于办公的本本内存较低的缘故,需要解读取数据时内存不足的原因. 操作流程: 方法与方式:首先是读取数据, ...

  2. LeetCode(303)Range Sum Query - Immutable

    题目 Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclus ...

  3. poj 1995 快速幂

    题意:给出A1,…,AH,B1,…,BH以及M,求(A1^B1+A2^B2+ … +AH^BH)mod M. 思路:快速幂 实例 3^11  11=2^0+2^1+2^3    => 3^1*3 ...

  4. 算法学习记录-排序——插入排序(Insertion Sort)

    插入排序: 在<算法导论>中是这样描述的 这是一个对少量元素进行排序的有效算法.插入排序的工作机理与打牌时候,整理手中的牌做法差不多. 在开始摸牌时,我们的左手是空的,牌面朝下放在桌子上. ...

  5. NPM包的安装及卸载

    NPM全名:node package manager,是node包管理工具,负责安装.卸载.更新等.新版的NodeJS已经集成了npm.所以装好NodeJS的同时,npm也已经装好了! 可以用cmd命 ...

  6. 光学字符识别OCR-2

    灰度聚类 接着我们就对图像的色彩进行聚类.聚类的有两个事实依据:         1.灰度分辨率   肉眼的灰度分辨率大概为40,因此对于像素值254和255,在我们肉眼看来都 只是白色:       ...

  7. Hive学习笔记(三)-- DML和DDL操作

    01-Hive表的DDL操作--修改表 创建一个分区表并加载数据 查询数据 修改表 加载数据 查询一下 另外一个命令查询表的分区 如何删除一个分区呢 查询一个,分区被删除了 修改表名 查询改名的新表的 ...

  8. Django Form one

    前戏: FromData:三种方式获取FromData 1. 创建一个FromData 的对象,然后再用append 的方法追个添加键值对 var formdata = new FormData(); ...

  9. java append方法

    JAVA 中 Stringbuffer 有append()方法  Stringbuffer其实是动态字符串数组  append()是往动态字符串数组添加,跟“xxxx”+“yyyy”相当那个‘+’号  ...

  10. python 学习分享-基础篇

    1.python起手式 写下第一个代码,打印‘hello world’ print('hello world') 2.变量 变量是为了存储信息,在程序中被调用,标识数据名称或类型. 变量定义的规则: ...