您的位置:首页 > 编程语言 > Go语言

cf 507E Breaking Good 最短路

2015-02-03 19:47 253 查看
在一个有n个城市m条边的国家,有一个犯罪团伙。这个犯罪团伙想要抢银行。犯罪团伙基地在城市1,银行在城市n。有个人Walter想要加入这个犯罪团伙,于是为了过的团伙高层的信任,Walter必须担任一项的任务,那就是在基地到银行之间选出一条最短路。这个国家有若干公路在维修,于是你需要将最短路径上的公路修好,为了阻止别的警察追击我方,还必须将所有的不在最短路上的公路炸毁。假如有多条最短路,那么需要选择影响值最小的一条最短路(影响值=需要维修的公路数+需要炸毁的公路数).

扩大边权的技巧,一开始影响值是m,走一条完好的路影响值减一,走一条坏路影响值加一,所以即求一条最短路,若有多条最短路那么走完好的路最多的。

#include <cstdio>
#include <cstring>
#include <queue>
#define ll long long
using namespace std;
#define maxn 101000
const ll inf = 0x3f3f3f3f3f3f3f;
int s[maxn],t[maxn],is[maxn];
int head[maxn],cnt;
int pre[maxn],preE[maxn];
int n,m;
ll dist[maxn];
int vis[maxn];
struct node
{
int u,v,id,next;
ll w;
}e[maxn*2];

void add(int u,int v,int id,ll w)
{
e[cnt].u=u;
e[cnt].v=v;
e[cnt].id=id;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt++;
}

void spfa()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) dist[i]=inf;
queue <int> Q;
dist[1]=0;
Q.push(1);
memset(pre,-1,sizeof(pre));
while(!Q.empty())
{
int u=Q.front(); Q.pop(); vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(dist[v] > dist[u] + e[i].w)
{
dist[v]=dist[u]+e[i].w;
pre[v]=u;
preE[v]=e[i].id;
if(!vis[v])
{
Q.push(v);
vis[v]=1;
}
}
}
}
}

int main()
{
scanf("%d%d",&n,&m);
int x,y,z;
cnt=0;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
s[i]=x;t[i]=y;is[i]=z;
add(x,y,i,maxn+1-z);
add(y,x,i,maxn+1-z);
}
spfa();
memset(vis,0,sizeof(vis));
for(int i=n;pre[i]!=-1;i=pre[i])
{
int id=preE[i];
if(is[id]==0)   vis[id]=2;
if(is[id]==1)   vis[id]=1;
}
for(int i=0;i<m;i++)
if(vis[i]==0&&is[i]==1)
vis[i]=2;
int tot=0;
for(int i=0;i<m;i++)
if(vis[i]==2) tot++;
printf("%d\n",tot);
for(int i=0;i<m;i++)
if(vis[i]==2)
printf("%d %d %d\n",s[i],t[i],1-is[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: