缩点(模板)P3387
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=10000+15; 4 int n,m,sum,tim,s; 5 int p[maxn],head[maxn],sd[maxn],dfn[maxn],low[maxn];//DFN(u)为节点u搜索被搜索到时的次序编号(时间戳), 6 //Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号 7 int vis[maxn];//栈只为了表示此时是否有父子关系 8 int h[maxn],in[maxn],dist[maxn]; 9 struct EDGE{ int to;int next;int from; }edge[maxn*10],ed[maxn*10]; 10 void add(int from,int to){ 11 edge[++sum].next=head[from]; 12 edge[sum].from=from; 13 edge[sum].to=to; 14 head[from]=sum; 15 } 16 stack<int>q; 17 void tarjan(int x) 18 { 19 low[x]=dfn[x]=++tim; 20 q.push(x);vis[x]=1; 21 for (int i=head[x];i;i=edge[i].next) 22 { 23 int v=edge[i].to; 24 if(!dfn[v]){ 25 tarjan(v); 26 low[x]=min(low[x],low[v]); 27 } 28 else if(vis[v]){ 29 low[x]=min(low[x],low[v]); 30 } 31 } 32 if(dfn[x]==low[x]){ 33 int y; 34 while(y=q.top()){ 35 q.pop(); 36 sd[y]=x; 37 vis[y]=0; 38 if (x==y) 39 break; 40 p[x]+=p[y]; 41 } 42 } 43 } 44 int topo() 45 { 46 queue<int>q; 47 int tot=0; 48 for(int i=1;i<=n;i++) 49 if(sd[i]==i&&!in[i]) 50 q.push(i),dist[i]=p[i]; 51 while(!q.empty()){ 52 int k=q.front();q.pop(); 53 for(int i=h[k];i;i=ed[i].next){ 54 int v=ed[i].to; 55 dist[v]=max(dist[v],dist[k]+p[v]); 56 if(--in[v]==0)q.push(v); 57 } 58 } 59 int ans=0; 60 for(int i=1;i<=n;i++) 61 ans=max(ans,dist[i]); 62 return ans; 63 } 64 int main() 65 { 66 scanf("%d%d",&n,&m); 67 for(int i=1;i<=n;i++) 68 scanf("%d",&p[i]); 69 for(int i=1,u,v;i<=m;i++){ 70 scanf("%d%d",&u,&v); 71 add(u,v); 72 } 73 for(int i=1;i<=n;i++) 74 if(!dfn[i])tarjan(i); 75 for(int i=1;i<=m;i++){ 76 int x=sd[edge[i].from],y=sd[edge[i].to]; 77 if (x!=y){ 78 ed[++s].next=h[x]; 79 ed[s].to=y; 80 ed[s].from=x; 81 h[x]=s; 82 in[y]++; 83 } 84 } 85 printf("%d",topo()); 86 return 0; 87 }
#include<bits/stdc++.h>
using namespace std;
const int maxn=10000+15;
int n,m,sum,tim,top,s;
int p[maxn],head[maxn],sd[maxn],dfn[maxn],low[maxn];//DFN(u)为节点u搜索被搜索到时的次序编号(时间戳),
//Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号
int stac[maxn],vis[maxn];//栈只为了表示此时是否有父子关系
int h[maxn],in[maxn],dist[maxn];
struct EDGE{ int to;int next;int from; }edge[maxn*10],ed[maxn*10];
void add(int from,int to){
edge[++sum].next=head[from];
edge[sum].from=from;
edge[sum].to=to;
head[from]=sum;
}
void tarjan(int x)
{
low[x]=dfn[x]=++tim;
stac[++top]=x;vis[x]=1;
for (int i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(vis[v]) low[x]=min(low[x],low[v]);
}
if(dfn[x]==low[x]){
int y;
while(y=stac[top--]){
sd[y]=x;
vis[y]=0;
if (x==y) break;
p[x]+=p[y];
}
}
}
int topo()
{
queue<int>q;
int tot=0;
for(int i=1;i<=n;i++)
if(sd[i]==i&&!in[i])
q.push(i),dist[i]=p[i];
while(!q.empty())
{
int k=q.front();q.pop();
for(int i=h[k];i;i=ed[i].next){
int v=ed[i].to;
dist[v]=max(dist[v],dist[k]+p[v]);
if(--in[v]==0)q.push(v);
}
}
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,dist[i]);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&p[i]);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=m;i++)
{
int x=sd[edge[i].from],y=sd[edge[i].to];
if (x!=y)
{
ed[++s].next=h[x];
ed[s].to=y;
ed[s].from=x;
h[x]=s;
in[y]++;
}
}
printf("%d",topo());
return 0;
}

浙公网安备 33010602011771号