题目: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 }