您的位置:首页 > 其它

Codeforces Gym 100338C Important Roads 最短路+Tarjan找桥

2015-08-21 19:42 357 查看
原题链接: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(0), 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 + 1, INF);
que.push(node(s, 0));
d[s] = 0;
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 = 0; 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=0;
bool vis[MAX_N];
int sum=0;
bool isBridge[MAX_M];

bool hasSame[MAX_M];

void Tarjan(int u,int p) {
father[u] = p;
dfn[u] = low[u] = ++ind;
vis[u] = 1;
for (int i = 0; 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] = 1;
}
}
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 = 0; 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]=1;
continue;
}
it=se.find(f0);
if(it!=se.end()){
hasSame[it->id]=1;
continue;
}
se.insert(f);
G[u].push_back(edge(v, c, i));
G[v].push_back(edge(u, c, i));
}

dijkstra(1, d);
dijkstra(n, rd);
ll sd = d
;
for (int i = 1; i <= n; i++)
for (int j = 0; 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 = 1;
}
Tarjan(1,0);
int tot = 0;
for (int i = 1; i <= n; i++)
for (int j = 0; j < G[i].size(); j++)
if (isBridge[G[i][j].id])
ans[G[i][j].id + 1] = 1;
for (int i = 1; i <= m; i++)if ((!hasSame[i-1])&&ans[i])tot++;
printf("%d\n", tot);
for (int i = 1; i <= m; i++)
if (ans[i]&&(!hasSame[i-1]))
printf("%d ", i);
printf("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: