10.18T2 tarjan缩点+分层图SPFA
吃土的DLZ
Problem Background
众所周知,DLZ喜欢吃土,总有一天,他要把学校的土吃完。
Problem Description
DLZ终于想起了他还要吃土,为了弥补之前一直没有吃土的遗憾,他决定这次要尽 可能去更多的地方吃土,学校可以看做有n个点联通的有向图,DLZ可以在学校随意游 走。DLZ所在的教室为一号节点,由于他还要上课,所以他必须在吃完土之后回到一号 节点。DLZ不是一般人,可以在学校的道路上逆行当路霸,但是DLZ是有高度社会责任 感的人,他不会为了一己私利而频繁破坏学校秩序,所以他最多只会逆行一次。额,那 么,有奖竞猜开始了,DLZ最多会去几个地方吃土?获胜者将获得bashu无限饭卡。
Input
第一行两个整数n,m。
第2到第m+1行,每行两个整数x,y,表示有一条x到y的有向边
Output
一个整数,DLZ最多会去几个点。
Sample Input
7 10
1 2
3 1
2 5
2 4
3 7
3 5
3 6
6 5
7 2
4 7
Sample Output
6
Data Scale
测试数据点 |
n |
m |
1~4 |
≤100 |
≤500 |
5,6 |
≤10000 |
≤20000 |
7~14 |
≤100000 |
≤100000 |
首先很显然一个联通块内可以不逆行任意到达,所以我们tarjan缩个点
然后发现只用一次逆行与分层图很像,把dis分成两个dis[x][1]和dis[x][0]代表没使用和使用,跑一个分层图而不是枚举每条边了,复杂度期望O(n+m)
在调的时候还是循环i,j搞混,引以为戒,同时慎用位运算判奇偶
说实话还是比较简单的
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #define N 500005 6 using namespace std; 7 struct node { 8 int u,v,w; 9 } e[N],e1[N]; 10 int first[N],nxt[N],cnt; 11 void add(int u,int v){ 12 e[++cnt].u=u; 13 e[cnt].v=v; 14 nxt[cnt]=first[u]; 15 first[u]=cnt; 16 } 17 int first1[N],nxt1[N],cnt1; 18 void add1(int u,int v,int w) { 19 e1[++cnt1].u=u; 20 e1[cnt1].v=v; 21 e1[cnt1].w=w; 22 nxt1[cnt1]=first1[u]; 23 first1[u]=cnt1; 24 } 25 int dfn[N],low[N],sign,instack[N],stack[N],top,bcc,belong[N],siz[N]; 26 void tarjan(int x) { 27 dfn[x]=low[x]=++sign; 28 instack[x]=1; 29 stack[++top]=x; 30 for(int i=first[x]; i; i=nxt[i]) { 31 int v=e[i].v; 32 if(!dfn[v]) { 33 tarjan(v); 34 low[x]=min(low[x],low[v]); 35 } else if(instack[v])low[x]=min(low[x],dfn[v]); 36 } 37 if(dfn[x]==low[x]) { 38 int t; 39 bcc++; 40 do { 41 siz[bcc]++; 42 t=stack[top--]; 43 belong[t]=bcc; 44 instack[t]=0; 45 } while(t!=x); 46 } 47 } 48 int max0=0; 49 int num[N],check[N]; 50 int f[N][2]; 51 struct T{ 52 int u,is; 53 }; 54 int dis[N][2],vis[N<<1],now; 55 void spfa(){ 56 queue<int>q; 57 memset(vis,0,sizeof vis); 58 memset(dis,0,sizeof dis); 59 dis[now][1]=0; 60 vis[now*2+1]=1; 61 q.push(now*2+1); 62 while(!q.empty()){ 63 int u=q.front(); 64 q.pop(); 65 vis[u]=0; 66 for(int i=first1[u/2];i;i=nxt1[i]){ 67 int v=e1[i].v; 68 if(e1[i].w){ 69 if(u%2){ 70 if(dis[v][0]<dis[u/2][1]+siz[v]){ 71 dis[v][0]=dis[u/2][1]+siz[v]; 72 if(!vis[2*v]){ 73 vis[2*v]=1; 74 q.push(2*v); 75 } 76 } 77 } 78 } 79 else{ 80 if(dis[v][u%2]<dis[u/2][u%2]+siz[v]){ 81 dis[v][u%2]=dis[u/2][u%2]+siz[v]; 82 if(!vis[2*v+u%2]){ 83 vis[2*v+u%2]=1; 84 q.push(2*v+u%2); 85 } 86 } 87 } 88 } 89 } 90 } 91 int read(){ 92 int x=0,f=1; 93 char c=getchar(); 94 while(!isdigit(c)){ 95 if(c=='-')f=-1; 96 c=getchar(); 97 } 98 while(isdigit(c)){ 99 x=(x<<3)+(x<<1)+c-'0'; 100 c=getchar(); 101 } 102 return x*f; 103 } 104 int main() { 105 freopen("soil.in","r",stdin); 106 freopen("soil.out","w",stdout); 107 int n,m; 108 n=read(),m=read(); 109 for(int i=1; i<=m; i++) { 110 int u,v; 111 u=read(),v=read(); 112 add(u,v); 113 } 114 for(int i=1;i<=n;i++) 115 if(!dfn[i])tarjan(i); 116 now=belong[1]; 117 for(int i=1; i<=cnt; i++) { 118 if(belong[e[i].u]==belong[e[i].v])continue; 119 add1(belong[e[i].u],belong[e[i].v],0); 120 add1(belong[e[i].v],belong[e[i].u],1); 121 } 122 spfa(); 123 cout<<max(dis[now][0],1); 124 return 0; 125 }
over