题意:跟上题一样,这题求哪些点可以进入负环。
思路:突然间想到把每一条边的方向改变一下就跟上题一模一样了,“看我,多聪明”。。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
const int N = 1009;
const int M = 2009;
const int INF = 0x3f3f3f3f;
int n,m;
struct LT{
int to,nex,dis;
} L[M];
int F[N],cnt;
void add(int f,int t,int d)
{
L[cnt].nex = F[f];
L[cnt].to = t;
L[cnt].dis = d;
F[f] = cnt++;
}
int que[N*N];
int coun[N],cir[N],dis[N],inque[N];
void dfs(int k)
{
cir[k] = 1;
for(int i=F[k];i;i=L[i].nex)
{
if(!cir[L[i].to])
dfs(L[i].to);
}
}
void solve()
{
memset(coun,0,sizeof(coun));
memset(cir,0,sizeof(cir));
memset(inque,0,sizeof(inque));
int front = 0, rear = 0;
for(int i=0;i<n;i++) que[i] = i;
rear= n;
memset(dis,0,sizeof(dis));
//dis[1] = 0;
while(rear>front)
{
int e = que[front++] ;
inque[e] = false;
coun[e]++;
if(coun[e]>n)
{
dfs(e);
continue;
}
for(int i=F[e];i;i=L[i].nex)
{
int to = L[i].to;
if(cir[to]) continue;
if(dis[to]>dis[e]+L[i].dis)
{
dis[to] = dis[e] + L[i].dis;
if(!inque[to])
{
if(coun[to]>(n>>1)&&front>0)
que[--front] = to;
else
que[rear++] = to;
inque[to] = true;
}
}
}
}
int f =0;
for(int i=0;i<n;i++)
if(cir[i]) dfs(i),f=1;
if(f==0)
{
printf(" impossible\n");
return ;
}else
{
for(int i=0;i<n;i++)
if(cir[i]) printf(" %d",i);
}printf("\n");
}
int main()
{
freopen("in.txt","r",stdin);
int cas,T=1;
scanf("%d",&cas);
while(cas--)
{
memset(F,0,sizeof(F));cnt = 1;
scanf("%d",&n);scanf("%d",&m);
int a,b,c;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&b,&a,&c);
add(a,b,c);
}
printf("Case %d:",T++);
solve();
}
return 0;
}