轰炸(bomb)
【题目描述】
有n座城市,城市之间建立了m条有向的地下通道。
你需要发起若干轮轰炸,每轮可以轰炸任意多个城市。但每次轰炸的城市中,不能存在两个不同的城市i,j满足可以通过地道从城市i到达城市j。
你需要求出最少需要多少轮可以对每座城市都进行至少一次轰炸。
【输入数据】
第一行两个整数n,m。接下来m行每行两个整数a,b表示一条从a连向b的单向边。
【输出数据】
一行一个整数表示答案。
【样例输入】
5 4
1 2
2 3
3 1
4 5
【样例输出】
3
【数据范围】
对于20%的数据,n,m<=10。
对于40%的数据,n,m<=1000。
对于另外30%的数据,保证无环。
对于100%的数据,n,m<=1000000。
听说是雅礼的一场比赛的。拿来给我们考啦!
第一题迭代加深搜索(打了半天32分)
题做的还是不够多,实力还是不够。
第二题也就是这题,明明想到正解了(很好想啊就是在没环的条件下)
可是...tarjan不会打(应该可以去死了qwq)
于是这道全世界人都会做的题(划掉),我没对。(竟然20分状压都写错了)
最近代码能力好像不大好啊,每次都会打错什么地方。
题解:当图中没环时,答案显然是最长链的长度,用拓扑解决。
所以使图没环就行了啊,那就用tarjan缩点啊!
可以用个vector记录每个缩了之后的点包含了哪些点就可以啦~
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#define N 1000000+10000
using namespace std;
vector<int>e[N];
struct node{
int to;
int next;
}e1[N+N],e2[N+N];
int n,m,temp,ans,t,Time,edgenum,tot,num;
int head[N],dfn[N],low[N],c[N],a[N],b[N],color[N],stack[N],in[N],Head[N],siz[N],f[N];
inline void add_edge(int u,int v){
e1[++edgenum].to=v;
e1[edgenum].next=head[u];
head[u]=edgenum;
}
inline void add(int u,int v){
e2[++num].to=v;
e2[num].next=Head[u];
Head[u]=num;
}
void tarjan(int u){
low[u]=dfn[u]=++Time;
c[u]=1;
stack[++tot]=u;
for(int i=head[u];i;i=e1[i].next){
int v=e1[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[v],low[u]);
}
else if(c[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
int tmp=0;
t++;
while(tmp!=u){
tmp=stack[tot--];
c[tmp]=0;
color[tmp]=t;
e[t].push_back(tmp);
}
}
}
void work(){
memset(dfn,0,sizeof(dfn));
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
add_edge(x,y);
a[i]=x;b[i]=y;
}
work();
for(int i=1;i<=t;i++) siz[i]=e[i].size();
for(int i=1;i<=t;i++)
for(int j=0;j<siz[i];j++){
int u=e[i][j];
for(int k=head[u];k;k=e1[k].next){
int v=e1[k].to;
if(color[u] != color[v]) add(color[u],color[v]),in[color[v]]++;
}
}
queue<int>q;
for(int i=1;i<=t;i++) if(!in[i]) q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
f[u]+=siz[u];
ans=max(ans,f[u]);
for(int i=Head[u];i;i=e2[i].next){
int v=e2[i].to;
f[v]=max(f[v],f[u]);
in[v]--;
if(!in[v]) q.push(v);
}
}
printf("%d\n",ans);
return 0;
}