Problem Description
“万妖穴中有若干小穴,每处小穴中皆有一只恶妖。小穴外设有封印,汝需消灭指定几处小穴中的恶妖方能解除该小穴封印,进而消灭穴中恶妖。”
“此处石壁所刻便是万妖穴中各穴的封印解除关系。”
“吾将瞬雷之法授于汝,汝消灭万妖穴中任一小穴皆仅需一瞬,愿汝尽快消灭各穴恶妖。”
“然消灭小穴后,其对下一处小穴的封印加强通道仍需若干时间方能闭上。”
“万妖穴中气息诡谲,恐有恶灵干扰,将使此段通道关闭时间变长。”
“汝需施法避免几处关键通道免于干扰,以使消灭整个万妖穴的时间免于延长。”
“万妖穴中或有部分小穴未设封印,汝可以此作为突破口。”
“吾将根据石壁所示,将各穴消灭顺序给予汝,汝自珍重。”
Input
每个输入文件中一组数据。
第一行两个正整数N、M(1<=N<=1000,0<=M<=N*(N-1)),表示万妖穴中小穴的个数及封印解除关系的条数。
接下来M行,每行三个整数a、b、c(0 <= a < N, 0 <= b < N, 0 < c <= 20),表示小穴b封印的解除依赖于消灭小穴a中的恶妖,且消灭小穴a中的恶妖后需要时长c才能关闭其对小穴b的封印加强通道(注意,必须将小穴b依赖的所有小穴中的恶妖消灭、并等待针对小穴b的封印加强通道都关闭后才能消灭小穴b)。假设N处小穴的编号分别是0~N-1。数据保证a不等于b,且每组封印解除关系a b最多出现一次。
Output
如果能够消灭所有小穴,那么在第一行输出YES与消灭所有恶妖的总时长,中间用一个空格隔开。然后从第二行开始输出关键路径,格式为用->连接的小穴编号。所谓关键路径是指,此路径上的所有通道的关闭时间均不可以被延长,否则会使消灭所有恶妖的时间变长;且关键路径上所有通道的关闭时长之和就是消灭所有恶妖的总时长。如果有多条关键路径,那么每行输出一条。注意,假设有两条关键路径a[1]->a[2]->…->a[k]->a[k+1]->…与b[1]->b[2]->…->b[k]->[k+1]->…,且a[1]==b[1]、a[2]==b[2]、…、a[k]==b[k]、a[k+1]< b[k+1],那么把关键路径a优先输出。数据保证关键路径条数不超过10000条。
如果不能消灭所有小穴,那么只输出一行,即NO与无法解除封印的小穴个数,中间用一个空格隔开。行末均不允许输出多余的空格。
Sample Input 1
5 6
0 1 3
0 3 4
0 2 1
1 3 1
2 3 2
4 0 2
Sample Output 1
YES 6
4->0->1->3
4->0->3
Sample Input 2
3 3
0 1 1
1 0 1
2 0 1
Sample Output 2
NO 2
Author
Shoutmon
Source
18浙大考研机试模拟赛
#include <bits/stdc++.h>
using namespace std;
vector<int> vx[1024],vy[1024],path[1024];
vector<vector<int>> v;
int A[1024][1024],indegree[1024],in[1024];
int ve[1024],vl[1024],n,m;
stack<int> stk;
bool topological()
{
queue<int> q;
for(int i=0;i<n;++i){
if(indegree[i]==0) q.push(i);
}
while(!q.empty()){
int x=q.front();
q.pop();
stk.push(x);
for(int y:vx[x]){
indegree[y]--;
if(indegree[y]==0) q.push(y);
ve[y]=max(ve[x]+A[x][y],ve[y]);
}
}
return (int)stk.size()==n;
}
int criticalpath()
{
if(topological()==0) return -1;
int maxval=*max_element(ve,ve+n);
fill(vl,vl+n,maxval);
while(!stk.empty()){
int y=stk.top();
stk.pop();
for(int x:vy[y])
vl[x]=min(vl[x],vl[y]-A[x][y]);
}
for(int x=0;x<n;++x){
for(int y:vx[x]){
int e=ve[x],l=vl[y]-A[x][y];
if(e==l) path[x].push_back(y);
}
}
return maxval;
}
void dfs(int x,vector<int> &rp)
{
if(path[x].size()==0){
v.push_back(rp);
return;
}
for(int y:path[x]){
rp.push_back(y);
dfs(y,rp);
rp.pop_back();
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=0;i<m;++i){
int x,y,w;
scanf("%d %d %d",&x,&y,&w);
vx[x].push_back(y);
vy[y].push_back(x);
A[x][y]=A[y][x]=w;
indegree[y]++;
in[y]++;
}
int res=criticalpath();
if(res==-1) printf("NO %d\n",n-(int)stk.size());
else{
printf("YES %d\n",res);
for(int i=0;i<n;++i){
if(in[i]==0&&path[i].size()!=0){
vector<int> rp(1,i);
dfs(i,rp);
}
}
sort(v.begin(),v.end());
for(auto &p:v){
int len=p.size();
for(int i=0;i<len;++i)
i==len-1?printf("%d\n",p[i]):printf("%d->",p[i]);
}
}
return 0;
}