题意:
n个城市m条道路, 任务是在城市1和城市n之间选择一个最短路径,当有多个最短路径的时候选择影响值最小的(被摧毁的和修好的路的数目总数最少) ,道路分已修复和未修复两种状态,在选择好最短路径后,要修复好最短路径上未工作的路,并破坏其他路径上工作的路径。
题解:
修复 = 最短路的长度 - 最短路上修好的路
破坏的道路 = 整张图上修好的路 - 最短路径上修好的路
影响值= 修复+破化的道路
= 最短路上没修好的路+非最短路上修好的路
= 最短路的长度 - 最短路上修好的路 + 整张图上修好的路 - 最短路上修好的路
= 最短路的长度 + 整张图上修好的路 - 2 * 最短路上修好的路
所以要使影响值最小应该使得最短路径上面工作的道路最多
先spfa得到最短路
如果最短路相同,再判断路上修好的路的个数(在spfa的过程中记录)
根据公式得到影响值,影响值也就是题目要求输出的k
用pre实现路径存储,输出最短路上未修好的路
bool bo[]记录最短路径上哪些点出现过
代码:
代码内详细注释
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
int INF= 0x3f3f3f3f;
const int maxn=1e5+9;
struct node{
int u,v,w;
}a[maxn];
//int vis[maxn];
int n,m;
int tot=0;//求路径中已修好的数量
pair<int,int>dis[maxn],pre[maxn];
bool vis[maxn],bo[maxn];
vector<pair<int,int> > edge[maxn];//存路径
queue<int>q;
void spfa()
{
for(int i=1;i<=n;i++)dis[i]=make_pair(INF,0);
dis[1].first=0;
q.push(1);
vis[1]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(pair<int,int> tmp:edge[u])
{
int v=tmp.first;
int w=a[tmp.second].w;
bool xx=((dis[v].first==dis[u].first+1)&&(dis[v].second<dis[u].second+w));
//如果都是最短路,那就要已修好道路多的
if(dis[v].first>dis[u].first+1||xx)
{
dis[v].first=dis[u].first+1;
dis[v].second=dis[u].second+w;
pre[v]=make_pair(u,tmp.second);//存入上一个点以及编号
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i].u>>a[i].v>>a[i].w;
edge[a[i].u].push_back(make_pair(a[i].v,i));//存下路径和序号
edge[a[i].v].push_back(make_pair(a[i].u,i));
tot+=a[i].w;
}
spfa();
int k;
k=dis[n].first+tot-2*dis[n].second;
//dis[n].first表示最短路的长度
// dis[n].second表示最短路上已修好的路
cout<<k<<endl;
int now=n;
while(now!=1)
{
int temp=pre[now].second;//上一个点的编号
if(a[temp].w==0)
cout<<a[temp].u<<" "<<a[temp].v<<" "<<1<<endl;
bo[temp]=1;//标记最短路上的路径
now=pre[now].first;
}
for(int i=1;i<=m;i++)
{
if(!bo[i]&&a[i].w==1)//如果不是最短路上的&&路是修好的
cout<<a[i].u<<" "<<a[i].v<<" "<<0<<endl;
}
return 0;
}

京公网安备 11010502036488号