airline

题目描述

A 国有 n 个城市从 1 到 n 编号,在城市间有 m 条单向航线。 A 国首都位于编号为 w 的城市,现在 A 国政府希望在首都召开会 议,就想要让各地人民都能够通过若干条航线到达首都,那么至少需 要新建多少条航线?(可能有重边和自环)

输入输出格式

输入格式:

 

第一行三个整数 n,m,w 接下来 m 行,每行两个整数 xi,yi,表示存在一条从 xi 到 yi 城市 的单向航线

 

输出格式:

 

一个整数表示最小需要新建多少条航线

 

输入输出样例

输入样例#1:  复制
5 4 1
2 1
1 2
2 3
3 4
输出样例#1:  复制
2

说明

对于 20%的数据 n<=10 m<=10 对于 40%的数据 n<=100 m<=100 对于 100%的数据 n<=10^6 m<=10^6

老师出的毒瘤题

本来想让我们写tarjin,结果没人写(没人会写)

题目给有向图,先反着建图,反着扫把能直接到终点的点标记

然后正这扫,一个点正反都没扫,就进深搜,只扫着个点连着的一个点(我也只记录了一个点),一直扫下去,如果扫到以前扫过的点,答案数就不用+1了,不然答案数+1

扫的过程中的点都标记为扫过

为什么只扫一个

1.扫的这个点能到终点或以前把他和终点建过边,高兴地返回

2。扫的这个天目前还不能到终点,那就标记为能到终点,答案加一,虽然按最开始扫的点不是最优解,但全局上不变,你以后肯定还得连

#include<bits/stdc++.h>

using namespace std;

int n,m,s,x,y,ans,a[1000001];

vector<int>f[1000001];

bool sao[1000001],zou[1000001];

queue<int>q;

void spfa()

{

         q.push(s);

         sao[s]=1;

         while(q.empty()==0)

         {

                   int u=q.front();q.pop();

                   for(int i=0;i<f[u].size();i++)

                   {

                            int w=f[u][i];

                            if(sao[w]==0)

                            {

                                     sao[w]=1;

                                     q.push(w);

                            }

                   }

         }

}

bool dfs(int k)

{

         if(a[k]==0)

         {

                   return 0;

         }

         if(zou[a[k]]==0)

         {

                   zou[a[k]]=1;

                   dfs(a[k]);

         }

         else

         return 1;

}

int main()

{

         cin>>n>>m>>s;

         for(int i=0;i<m;i++)

         {

                   scanf("%d%d",&x,&y);

                   if(x!=y)

                   {

                            f[y].push_back(x);

                            a[x]=y;

                   }

         }

         spfa();

         for(int i=1;i<=n;i++)

         {

                   if(sao[i]==0&&zou[i]==0)

                   {

                            zou[i]=1;

                            if(dfs(i)==0)

                            {

                                     ans++;

                            }

                   }

         }

         cout<<ans;

}

转载于:https://www.cnblogs.com/fanhao050109/p/11234962.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值