Tarjan縮點模板 (洛谷P3387)
阿新 • • 發佈:2018-01-21
struct color hide 計算 min -m etc getch 有向圖
題目背景
縮點+DP
題目描述
給定一個n個點m條邊有向圖,每個點有一個權值,求一條路徑,使路徑經過的點權值之和最大。你只需要求出這個權值和。
允許多次經過一條邊或者一個點,但是,重復經過的點,權值只計算一次。
輸入輸出格式
輸入格式:
第一行,n,m
第二行,n個整數,依次代表點權
第三至m+2行,每行兩個整數u,v,表示u->v有一條有向邊
輸出格式:
共一行,最大的點權之和。
輸入輸出樣例
輸入樣例#1: 復制2 2 1 1 1 2 2 1輸出樣例#1: 復制
2
說明
n<=10^4,m<=10^5,|點權|<=1000 算法:Tarjan縮點+DAGdp
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #define maxn 100010 6 using namespace std; 7 inline int read() 8 { 9 int x=0,f=1; 10 char ch=getchar(); 11 while(ch<‘0‘||ch>‘9‘) 12 { 13 if(ch==‘-‘View Code) f=-1; 14 ch=getchar(); 15 } 16 while(ch>=‘0‘&&ch<=‘9‘) 17 { 18 x=x*10+ch-‘0‘; 19 ch=getchar(); 20 } 21 return x*f; 22 } 23 int head[maxn],ecnt,vis[maxn],dis[maxn],low[maxn],dfn[maxn],stk[maxn],tot,colortm,color[maxn],top,f[maxn],ans,w[maxn],x[maxn],y[maxn],n,m;24 struct edge 25 { 26 int u,v,next; 27 }E[maxn]; 28 void add(int u,int v) 29 { 30 E[++ecnt].u=u; 31 E[ecnt].v=v; 32 E[ecnt].next=head[u]; 33 head[u]=ecnt; 34 } 35 void tarjan(int u) 36 { 37 vis[u]=1; 38 stk[++top]=u; 39 low[u]=dfn[u]=++tot; 40 for(int i=head[u];i;i=E[i].next) 41 { 42 int v=E[i].v; 43 if(!dfn[v]) 44 { 45 tarjan(v); 46 low[u]=min(low[u],low[v]); 47 } 48 else if(vis[v]) low[u]=min(low[u],dfn[v]); 49 } 50 if(dfn[u]==low[u]) 51 { 52 ++colortm; 53 vis[u]=0; 54 while(stk[top+1]!=u) 55 { 56 vis[stk[top]]=0; 57 color[stk[top]]=colortm; 58 f[colortm]+=w[stk[top]]; 59 ans=max(ans,f[colortm]); 60 top--; 61 } 62 } 63 } 64 void bfs(int x) 65 { 66 memset(vis,0,sizeof(vis)); 67 memset(dis,0,sizeof(dis)); 68 queue<int>q; 69 q.push(x); 70 vis[x]=1; 71 dis[x]=f[x]; 72 while(!q.empty()) 73 { 74 int u=q.front(); 75 for(int i=head[u];i;i=E[i].next) 76 { 77 int v=E[i].v; 78 if(dis[v]<dis[u]+f[v]) 79 { 80 dis[v]=dis[u]+f[v]; 81 if(!vis[v]) 82 { 83 q.push(v); 84 vis[v]=1; 85 } 86 } 87 } 88 q.pop(); 89 vis[u]=0; 90 } 91 for(int i=1;i<=colortm;++i) ans=max(ans,dis[i]); 92 } 93 int main() 94 { 95 n=read();m=read(); 96 for(int i=1;i<=n;++i) w[i]=read(); 97 for(int i=1;i<=m;++i) 98 { 99 int a=read(),b=read(); 100 add(a,b); 101 x[i]=a; 102 y[i]=b; 103 } 104 for(int i=1;i<=n;++i) 105 { 106 if(!dfn[i]) tarjan(i); 107 } 108 memset(head,0,sizeof(head)); 109 memset(E,0,sizeof(E)); 110 ecnt=0; 111 for(int i=1;i<=m;++i) 112 { 113 if(color[x[i]]!=color[y[i]]) 114 { 115 add(color[x[i]],color[y[i]]); 116 } 117 } 118 119 for(int i=1;i<=colortm;++i) 120 bfs(i); 121 printf("%d\n",ans); 122 return 0; 123 }
Tarjan縮點模板 (洛谷P3387)