您的位置:首页 > 理论基础 > 数据结构算法

Codeforces Round #Pi (Div. 2) E. President and Roads (最短路+强连通求割边)

2015-08-07 15:43 609 查看
题目地址:codeforces #pi (DIV2) E

题目很水。。就是先求两边最短路,然后把可能为最短路的边挑出来,然后判断是否yes只需要转化成无向图跑一遍tarjan,找出割边,割边就是yes,然后剩下的边就让它的值为最短路-1就行了,如果-1后变成了非正数,就是no.

但是!!!居然卡spfa!!那是不是说cf以后就不能用可以卡的算法了。。完全可以出组数据来卡这些算法。。。比如spfa,isap。。。

于是为了这题,又看了一遍迪杰斯特拉算法。。

代码如下:

#include <cstdio>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <cmath>
#include <map>
#include <stack>
#include <algorithm>
using namespace std ;
#pragma comment(linker, "/STACK:102400000,102400000")
#define LL __int64
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
const int MAXN=100000+10;
int head[MAXN], cnt, source, sink, vis[MAXN], ok[MAXN];
LL d[2][MAXN];
struct N
{
int u, v;
LL w;
}fei[MAXN];
struct node
{
int u, v, next;
LL w;
}edge[MAXN];
void add(int u, int v, LL w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void init(int n, int x)
{
memset(head,-1,sizeof(head));
cnt=0;
for(int i=1;i<=n;i++){
d[x][i]=(LL)1e15;
}
}
struct Heap
{
LL w;
int id;
Heap () {}
Heap(LL w, int id): w(w),id(id) {}
bool operator < (const Heap &a) const{
return w>a.w;
}
};
priority_queue<Heap>q;
void dijk(int x, int st)
{
memset(vis,0,sizeof(vis));
while(!q.empty()) q.pop();
q.push(Heap(0,st));
d[x][st]=0;
while(!q.empty()){
int u=q.top().id;
q.pop();
if(vis[u]) continue ;
vis[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(d[x][v]>d[x][u]+edge[i].w){
d[x][v]=d[x][u]+edge[i].w;
q.push(Heap(d[x][v],v));
}
}
}
}
int dfn[MAXN], low[MAXN], indx;
vector<pair<int,int> >G[MAXN];
void init1(int n)
{
memset(dfn,0,sizeof(dfn));
indx=0;
memset(ok,0,sizeof(ok));
for(int i=1;i<=n;i++){
G[i].clear();
}
}
void tarjan(int u, int fa)
{
dfn[u]=low[u]=++indx;
int flag=0;
for(int i=0;i<G[u].size();i++){
int v=G[u][i].first;
if(v==fa&&!flag){
flag=1;
continue ;
}
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(dfn[u]<low[v]){
ok[G[u][i].second]=1;
}
}
else low[u]=min(low[u],dfn[v]);
}
}
int main()
{
int n, m, i, u, v, j;
LL w;
while(scanf("%d%d%d%d",&n,&m,&source,&sink)!=EOF){
init(n,0);
for(i=0;i<m;i++){
scanf("%d%d%I64d",&fei[i].u,&fei[i].v,&fei[i].w);
add(fei[i].u,fei[i].v,fei[i].w);
}
dijk(0,source);
init(n,1);
for(i=0;i<m;i++){
add(fei[i].v,fei[i].u,fei[i].w);
}
dijk(1,sink);
init1(n);
for(i=0;i<m;i++){
u=fei[i].u;
v=fei[i].v;
if(d[0][u]+d[1][v]+fei[i].w==d[0][sink]){
G[u].push_back(make_pair(v,i));
G[v].push_back(make_pair(u,i));
}
}
tarjan(source,-1);
for(i=0;i<m;i++){
if(ok[i]){
puts("YES");
continue ;
}
u=fei[i].u;v=fei[i].v;
w=d[0][sink]-d[0][u]-d[1][v];
w--;
if(w<=0) puts("NO");
else printf("CAN %I64d\n",fei[i].w-w);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息