题意:
朋友圈,如果彼此都认为对方是朋友帮忙就无花费,否则花费为1,如果是一个环也认为彼此是朋友。
思路:
强联通分量缩点,重新造边,跑最短路。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int MAXN =100000 ;
const int MAXM =100000 ;
using namespace std;
const int maxn=100005;
struct node ///优先队列, 在距离相同时选最小花费
{
int v,w,dis;
node(int _v=0,int _w=0,int _dis=0):v(_v),w(_w),dis(_dis){}
bool operator <(const node &r)const
{
if(dis!=r.dis)
return dis>r.dis;
else
return w>r.w;
}
};
vector<node> vec[maxn];///存边
struct Edge
{
int to,next;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,top;
int scc;
int vis[maxn];
int dis[maxn];///存最短路径
const int inf=0x3f3f3f3f;
bool Instack[MAXN];
void addedge(int u,int v)
{
edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
}
void dijk(int st,int n)
{
for(int i=1;i<=n;i++)
{
vis[i]=0;
dis[i]=inf;
}
priority_queue<node> q;
dis[st]=0;
q.push(node(st,0,0));
node tmp;
while(!q.empty())
{
tmp=q.top();
q.pop();
int u=tmp.v;
if(vis[u])
continue;
vis[u]=1;
for(int i=0;i<vec[u].size();i++)
{
int v=vec[u][i].v;
int cost=vec[u][i].w;
if(!vis[v]&&dis[v]>=dis[u]+cost)
{
dis[v]=dis[u]+cost;
q.push(node( v,cost,dis[v]));
}
}
}
if(dis[Belong[n]]!=inf)
printf("%d\n",dis[Belong[n]]);
else
printf("-1\n");
}
void Tarjan(int u)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u];i != -1;i = edge[i].next)
{
v = edge[i].to;
if(!DFN[v])
{
Tarjan(v);
if(Low[u] > Low[v])
Low[u] = Low[v];
}
else if(Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if(Low[u] == DFN[u])
{
scc++;
do
{
v = Stack[--top];
Belong[v] = scc;
Instack[v] = false;
}
while( v!= u );
}
}
int in[MAXN],out[MAXN];
void solve(int N)
{
for(int i=1;i<=N;i++)
vec[i].clear();
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
Index = scc = top = 0;
for(int i = 1;i <= N;i++)
if(!DFN[i])
Tarjan(i);
for(int u = 1;u <= N;u++)
{
for(int i = head[u];i != -1;i = edge[i].next)
{
int v = edge[i].to;
if(Belong[u] != Belong[v])
{
vec[Belong[u]].push_back(node(Belong[v],1,0));
}
}
}
/*
for(int i=1;i<=scc;i++)
{
for(int j=0;j<vec[i].size();j++)
{
printf("%d--%d\n ",i,vec[i][j]);
}
}*/
dijk(Belong[1],N);
}
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
int main()
{
int n,m;
int v;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
int u,v;
for(int i = 1;i <= m;i++)
{
scanf("%d%d",&u,&v);
u++,v++;
addedge(u,v);
}
solve(n);
}
return 0;
}