CF-507E

CF-507E


题目大意

就是给出一张图,每条边有一个开放情况,0表示关闭,1表示打开。现在有一个人在1号点,要去\(n\)号点。特别的,这个人要走最短路(无论路是否开放)。他可以用1的花费打开一条路,也可以用1的花费关闭1条路。他希望除了自己走的最短路之外的路全部关闭,自己走的最短路全部开放,求这个人可能的最小花费。并且输出做出改变的路的更改后的开放情况。

题目分析

不管三七二十一可以先把所有的最短路跑出来,因为边的权值都是1,所以两遍广搜就能完事。

对于之后的操作,容易想到带着那个0和1的权值,重建一个有向图,跑一遍spfa最长路就可以出解。至于输出方案,可以使用跑完最长路之后的dis数组,暴力的使用搜索,检查每一条路径是否能符合要求。要注意的是,如果从u访问一个点v时,之前权值和大于等于u的点向v访问都无法成功的话,u也无法成功,可以减去很多搜索量。

代码

#include <bits/stdc++.h>
const int MAXN=1e5+7;
using namespace std;
int num,head[MAXN],Head[MAXN],dep[MAXN],b[MAXN],n,m,s,t,numm,dis[MAXN],to[MAXN],change[MAXN],flag;
struct E{
	int u,v,w;
}e[MAXN<<1];
struct po{
	int nxt,to,dis,num;
}edge[MAXN<<1],Edge[MAXN<<1];
inline void add_edge(int from,int to,int dis)
{
	edge[++num].nxt=head[from];
	edge[num].to=to;
	edge[num].dis=dis;
	head[from]=num;
}
inline void Add_edge(int from,int to,int dis)
{
	Edge[++numm].nxt=Head[from];
	Edge[numm].to=to;
	Edge[numm].dis=dis;
	Head[from]=numm;
}
inline void bfs1(){
	memset(dep,0,sizeof(dep));
	queue<int> q;
	q.push(s);
	dep[s]=1;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=Head[u];i;i=Edge[i].nxt){
			int v=Edge[i].to;
			if(dep[v]) continue;
			dep[v]=dep[u]+1;
			if(v==t) return;
			q.push(v); 
		}
	}
}
inline void bfs2()
{
	queue<int> q;
	q.push(t);
	b[t]=1;
	while(!q.empty()){
		int u=q.front(); q.pop();
		for(int i=Head[u];i;i=Edge[i].nxt){
			int v=Edge[i].to;
			if(dep[v]==dep[u]-1){
				change[i]=0;
				add_edge(v,u,Edge[i].dis);
				edge[num].num=(i+1)/2;
				if(!b[v]) {
					b[v]=1;
					q.push(v);
				}
			}
		}
	}
}
inline void spfa()
{
	memset(b,0,sizeof(b));
	memset(dis,-1,sizeof(dis));
	queue<int> q;
	q.push(s);dis[s]=0;
	while(!q.empty()){
		int u=q.front();q.pop();b[u]=0;
		for(int i=head[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			if(dis[v]<dis[u]+edge[i].dis){
				dis[v]=dis[u]+edge[i].dis;
				if(!b[v]){
					b[v]=1;
					q.push(v);
				}
			}
		}
	}
}
inline void dfs(int u,int l)
{
	if(flag==1) return;
	if(l==dis[t]&&u==t){
		flag=1;
		return;
	}
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].to;
		if(l+edge[i].dis<=to[v]) continue;
		to[v]=l+edge[i].dis;
		change[edge[i].num]=1;
		dfs(v,to[v]);
		if(flag==1) return;
		change[edge[i].num]=0;
	}
}
int main()
{
	cin>>n>>m;
	s=1;t=n;
	for(int i=1;i<=m;i++){
		change[i]=2;
		cin>>e[i].u>>e[i].v>>e[i].w;
		int u,v,w;
		u=e[i].u;v=e[i].v;w=e[i].w;
		Add_edge(u,v,w);Add_edge(v,u,w);
	}
	bfs1();bfs2();
	spfa();
	memset(to,-1,sizeof(to));
	dfs(s,0);
	int ans=0;
	for(int i=1;i<=m;i++){
		if(change[i]!=1&&e[i].w==1){
		ans++;
		}
		if(change[i]==1&&e[i].w==0){
			ans++;
		}
	}
	printf("%d\n",ans);
	for(int i=1;i<=m;i++){
		if(change[i]!=1&&e[i].w==1){
			printf("%d %d 0\n",e[i].u,e[i].v);
		}
		if(change[i]==1&&e[i].w==0){
			printf("%d %d 1\n",e[i].u,e[i].v);
		}
	}
	return 0;
} 
posted @ 2020-11-21 14:45  ~victorique~  阅读(273)  评论(0编辑  收藏  举报
Live2D