题意:
给你n个点和m条道路,1表示道路没问题,0表示道路正在修,选取一条1->n的最短路,其中不属于最短路中的没问题的道路需炸毁,最短路上的需要修的道路我们要修好
求1到n之间的造成影响最小的最短路中会被影响的道路
方法:
因为走一条没问题的道路是不会造成影响的,走有问题的道路的是有影响的,所以我们在找最短路的时候,找到走没问题的道路的最多那一条即可,用迪杰斯特拉+堆优化 或者SPFA都行
PS:当时以为要影响最小然后最短,没想到是最短然后影响最小,我写了一下迪杰斯特拉+堆优化 和SPFA 发现所花时间差不多
代码1:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
#define maxm 200010
#define maxn 100010
#define INF 111111
struct node
{
int a, b, c, next;
node(){}
node(int a, int b, int c, int d):
a(a),b(b),c(c),next(d){}
}edge[maxm];
struct pp
{
int v, d1 ,d2;
bool operator < (const pp &x) const
{
if(d1!= x.d1)
return d1 > x.d1;
return d2< x.d2;
}
};
int n, m, tot;
int head[maxn], vis[maxn];
int dis[maxn], d[maxn], pre[maxn];
int ans[maxn];
priority_queue<pp> q;
void add(int x, int y, int z)
{
edge[++tot]= node(x, y, z, head[x]);
head[x]= tot;
}
void Dij()
{
memset(d, 0, sizeof d);
memset(vis, 0, sizeof vis);
for(int i= 1; i< maxn; i++)
dis[i]= INF;
pp N;
N.v= 1, N.d1= 0, N.d2= 0;
q.push(N);
while(!q.empty())
{
while(vis[N.v] && !q.empty())
{
N= q.top();
q.pop();
}
if(vis[N.v])
break;
vis[N.v]= 1;
dis[N.v]= N.d1;
d[N.v]= N.d2;
for(int i= head[N.v]; i!= -1; i= edge[i].next)
if(!vis[edge[i].b])
{
if(dis[N.v]+1< dis[edge[i].b] || (dis[N.v]+1 == dis[edge[i].b] && d[N.v]+edge[i].c> d[edge[i].b]))
{
pp M;
M.v= edge[i].b;
M.d1= dis[N.v]+1;
M.d2= d[N.v]+edge[i].c;
q.push(M);
dis[edge[i].b]= M.d1;
d[edge[i].b]= M.d2;
pre[edge[i].b]= i;
}
}
}
memset(ans, 0, sizeof ans);
int xx= n;
while(xx!= 1)
{
ans[(pre[xx]+1)/2]= 1;
xx= edge[pre[xx]].a;
}
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(head, -1, sizeof head);
int x, y, z;
tot= 0;
int sum= 0;
for(int i= 1; i<= m; i++)
{
scanf("%d %d %d",&x,&y,&z);
add(y, x, z);
add(x, y, z);
if(z)sum++;
}
Dij();
printf("%d\n",sum+dis[n]-2*d[n]);
for(int i= 2; i<= 2*m; i+=2)
if(ans[i/2]^edge[i].c)
printf("%d %d %d\n",edge[i].a,edge[i].b,edge[i].c^1);
}
return 0;
}
代码2:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
#define maxn 100010
#define maxm 200010
#define INF 111111
struct node
{
int a,v, c, next;
node(){}
node(int a,int v, int c, int next):
a(a),v(v), c(c), next(next){}
}edge[maxm];
struct pp
{
int v,d1,d2;
};
queue<int> q;
int n, m, tot;
int dis[maxn], d[maxn], pre[maxn], ans[maxn], head[maxn];
int vis[maxn];
void add(int x, int y, int z)
{
edge[++tot]= node(x, y, z, head[x]);
head[x]= tot;
}
void SPFA()
{
memset(d, 0, sizeof d);
memset(ans, 0, sizeof ans);
memset(vis, 0, sizeof vis);
for(int i= 1; i<= maxn; i++)
dis[i]= INF;
dis[1]= 0;
vis[1]= 1;
q.push(1);
while(!q.empty())
{
int v= q.front();
q.pop();
vis[v]= 0;
for(int i= head[v]; i!= -1; i= edge[i].next)
if(dis[v]+ 1 < dis[edge[i].v] || (dis[v]+1== dis[edge[i].v] && d[v]+ edge[i].c> d[edge[i].v]))
{
dis[edge[i].v]= dis[v]+ 1;
d[edge[i].v]= d[v]+ edge[i].c;
pre[edge[i].v]= i;
if(!vis[edge[i].v])
{
q.push(edge[i].v);
vis[edge[i].v]= 1;
}
}
}
int xx= n;
while(xx!= 1)
{
ans[(pre[xx]+1)/2]= 1;
xx= edge[pre[xx]].a;
}
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
tot= 0;
int sum= 0, x, y, z;
memset(head, -1, sizeof head);
for(int i= 1; i<= m; i++)
{
scanf("%d %d %d",&x,&y,&z);
add(y, x, z);
add(x, y, z);
if(z) sum++;
}
SPFA();
printf("%d\n",sum+dis[n]-2*d[n]);
for(int i= 2; i<= 2*m; i+=2)
if(ans[i/2]^edge[i].c)
printf("%d %d %d\n",edge[i].a,edge[i].v,edge[i].c^1);
}
return 0;
}