队爷的讲学计划 CH Round #59

题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划

题解:刚开始理解题意理解了好半天,然后发现好像就是tarjan之后求个最长链?

        然后题目规定了从1出发,那么就只将scc[1]放入初始队列。

        然后只有10分。。。 

        后来我发现了这样的情况:因为只有scc[1]放入了队列,所以其它入度为0的并没有被放入队列,这使得一些点的inp无法减到0,以致无法更新答案

        然后我就先从scc[1]dfs了一遍,先统计出每个点可通过scc[1]到达的度数,再拓扑排序,就过了。

        好题,怒赞!

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<iostream>
 7 #include<vector>
 8 #include<map>
 9 #include<set>
10 #include<queue>
11 #include<string>
12 #define inf 1000000000
13 #define maxn 550000
14 #define maxm 500+100
15 #define eps 1e-10
16 #define ll long long
17 #define pa pair<int,int>
18 #define for0(i,n) for(int i=0;i<=(n);i++)
19 #define for1(i,n) for(int i=1;i<=(n);i++)
20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
22 #define mod 1000000007
23 using namespace std;
24 inline int read()
25 {
26     int x=0,f=1;char ch=getchar();
27     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
28     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
29     return x*f;
30 }
31 int n,m,cnt,ti,tot,head[maxn],inp[maxn],dfn[maxn],low[maxn],sta[maxn],top;
32 int scc[maxn],s[maxn],f[maxn],a[maxn],b[maxn],c[maxn];
33 ll g[maxn];
34 struct edge{int go,next,w;}e[maxn];
35 queue<int> q;
36 inline void insert(int x,int y,int z)
37 {
38     e[++tot].go=y;e[tot].next=head[x];e[tot].w=z;head[x]=tot;
39 }
40 inline void tarjan(int x)
41 {
42     dfn[x]=low[x]=++ti;sta[++top]=x;
43     for(int i=head[x],y;i;i=e[i].next)
44      if(!dfn[y=e[i].go]) 
45       {
46           tarjan(y);low[x]=min(low[x],low[y]);
47       }
48      else if(!scc[y])low[x]=min(low[x],dfn[y]);
49     if(low[x]==dfn[x])
50      {
51          cnt++;int now=0;
52          while(now!=x)
53          {
54              now=sta[top--];scc[now]=cnt;s[cnt]++;
55          }
56      }
57 }
58 inline void dfs(int x)
59 {
60     for(int i=head[x];i;i=e[i].next)
61     {
62         int y=e[i].go;
63         inp[y]++;
64         if(inp[y]==1)dfs(y);
65     }
66 }
67 int main()
68 {
69     freopen("input.txt","r",stdin);
70     freopen("output.txt","w",stdout);
71     n=read();m=read();
72     for1(i,m){a[i]=read();b[i]=read();c[i]=read();insert(a[i],b[i],c[i]);}
73     for1(i,n)if(!dfn[i])tarjan(i);
74     memset(head,0,sizeof(head));tot=0;
75     for1(i,m)if(scc[a[i]]!=scc[b[i]])insert(scc[a[i]],scc[b[i]],c[i]);
76     for1(i,cnt)f[i]=0,g[i]=inf;
77     f[scc[1]]=g[scc[1]]=s[scc[1]];g[scc[1]]--;
78     dfs(scc[1]);
79     q.push(scc[1]);
80     //for1(i,cnt)if(!inp[i])q.push(i),f[i]=s[i],g[i]=s[i]-1;
81     while(!q.empty())
82     {
83         int x=q.front();q.pop();
84         for(int i=head[x];i;i=e[i].next)
85         {
86             int y=e[i].go;
87             inp[y]--;
88             if(!inp[y])q.push(y);
89             if(f[x]+s[y]>f[y])f[y]=f[x]+s[y],g[y]=g[x]+e[i].w+s[y]-1;
90             else if(f[x]+s[y]==f[y])g[y]=min(g[y],g[x]+e[i].w+s[y]-1);
91         }
92     }
93     int ans=0;
94     for1(i,cnt)
95     if(f[i]>f[ans])ans=i;
96     else if(f[i]==f[ans]&&g[i]<g[ans])ans=i;
97     printf("%d %lld
",f[ans],g[ans]);
98     return 0;
99 }
View Code
原文地址:https://www.cnblogs.com/zyfzyf/p/4069118.html