Fly | ||||||
| ||||||
Description | ||||||
Luck wanted to fly to other cities.After a long time to wait,he realized his dream finally.There are n citis numbered from 1 to n.Some cities have a one-way airline to other cities.Luke can fly through these airlines. Now ,Luck wants to know the maximum number of cities he can fly to. | ||||||
Input | ||||||
There are multiple test cases.Input data will be over at the end of the file.The first line of each test case is three positive integers n,m,s(1<=n<=100000,0<=m<=150000,1<=s<=n),standing for the number of cities,the number of airlines and the city which Luke is in. Then m lines follows,each line has two positive integers v and u(1<=v,u<=n),indicating that there is an airline from city v to city u. | ||||||
Output | ||||||
For each test case,output the maximum number of cities that Luke can fly to.Each test case should be printed in one line. | ||||||
Sample Input | ||||||
4 3 1 1 2 2 3 2 4 5 4 1 1 2 2 3 2 4 3 2 | ||||||
Sample Output | ||||||
3 4 | ||||||
Source | ||||||
2013黑龙江省省赛 |
题目大意:
给你N个点,M条有向边,主人公居住的点的编号,问主人公最多可以到达几个点(本身这个点也算)。
思路:
1、首先,如果我们想要判断主人公最多可以到达几个点,那么我们直接从起点求一次单源最长路即可,但是因为这个图是一个有向图,而且可能存在有向环,那么此时我们就不能直接跑最长路来求解,因为此时求最长路会陷入死循环,最长路值无限增大~。
2、那么我们首先将这个图跑Tarjan强连通缩点染色使得整个有向图变成一个DAG图(有向无环图),然后再跑最长路即可。
3、代码复杂了一些,谨慎一些即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
struct node2
{
int to,w;
}now,nex;
struct node
{
int from;
int to;
int next;
}e[175000];
vector<node2 >mp[103050];
int color[103050];
int low[103050];
int dfn[103050];
int stack[103050];
int vis[103050];
int head[103050];
int dis[103050];
int cont[103050];
int n,m,ss,sig,contt,cnt,tt;
void add(int from,int to)
{
e[contt].from=from;
e[contt].to=to;
e[contt].next=head[from];
head[from]=contt++;
}
void Tarjan(int u)
{
vis[u]=1;
low[u]=dfn[u]=cnt++;
stack[++tt]=u;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(vis[v]==0)Tarjan(v);
if(vis[v]==1)low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u])
{
sig++;
do
{
color[stack[tt]]=sig;
vis[stack[tt]]=-1;
}
while(stack[tt--]!=u);
}
}
void SPFA()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=sig;i++)dis[i]=0;
dis[color[ss]]=cont[color[ss]];
vis[color[ss]]=1;
queue<int >s;
s.push(color[ss]);
while(!s.empty())
{
int u=s.front();
s.pop();
vis[u]=0;
for(int i=0;i<mp[u].size();i++)
{
now=mp[u][i];
int v=now.to;
int w=now.w;
if(dis[v]<dis[u]+w)
{
dis[v]=dis[u]+w;
if(vis[v]==0)
{
vis[v]=1;
s.push(v);
}
}
}
}
int output=0;
for(int i=1;i<=sig;i++)
{
output=max(output,dis[i]);
}
printf("%d\n",output);
}
void Slove()
{
tt=-1;sig=0;cnt=1;
memset(cont,0,sizeof(cont));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(stack,0,sizeof(stack));
memset(color,0,sizeof(color));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)mp[i].clear();
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
Tarjan(i);
}
for(int i=1;i<=n;i++)
{
cont[color[i]]++;
}
for(int i=0;i<contt;i++)
{
if(color[e[i].from]!=color[e[i].to])
{
now.to=color[e[i].to];
now.w=cont[color[e[i].to]];
mp[color[e[i].from]].push_back(now);
//printf("%d %d\n",)
}
}
SPFA();
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&ss))
{
contt=0;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
Slove();
}
}