10.18T2 tarjan缩点+分层图SPFA

吃土的DLZ

Problem Background

众所周知,DLZ喜欢吃土,总有一天,他要把学校的土吃完。

Problem Description

DLZ终于想起了他还要吃土,为了弥补之前一直没有吃土的遗憾,他决定这次要尽 可能去更多的地方吃土,学校可以看做有n个点联通的有向图,DLZ可以在学校随意游 走。DLZ所在的教室为一号节点,由于他还要上课,所以他必须在吃完土之后回到一号 节点。DLZ不是一般人,可以在学校的道路上逆行当路霸,但是DLZ是有高度社会责任 感的人,他不会为了一己私利而频繁破坏学校秩序,所以他最多只会逆行一次。额,那 么,有奖竞猜开始了,DLZ最多会去几个地方吃土?获胜者将获得bashu无限饭卡

Input

第一行两个整数nm

2到第m+1行,每行两个整数xy,表示有一条xy的有向边

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

原文地址:https://www.cnblogs.com/saionjisekai/p/9809802.html