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;
}
对于作者转载文章,欢迎继续转载。
对于作者原创文章,请注明出处之后转载。