POJ_3160

http://poj.org/problem?id=3160

/* 题意:一个老师要给学生送礼物,每个学生不在同一宿舍,现在题目一个n个学生,m个边,每个学生有一个值, 要你求这个老师能得到的最大值 scc+dp dp[i]表示走到节点i能取到的最大值 */ #include<iostream> using namespace std; #define MAXN 30005 #define MAXM 150005 struct Node { int to; int next; }graph[MAXM], newgraph[MAXM];//原图,新图 int head1[MAXN], head2[MAXN], cnt1, cnt2, pt;//建图用的两个数组 int n, m;//顶点数,边数 int low[MAXN], dfn[MAXN], stack[MAXN], belong[MAXN];//tarjan算法用的常用数组 int index, num, top; bool instack[MAXN], visit[MAXN]; int val[MAXN], newval[MAXN]; int dp[MAXN]; int tms[MAXN];//用来储存拓扑排序的顺序 void init()//初始化 { index = num = top = 0; cnt1 = 0; cnt2 = 0; pt = 0; for(int i=0; i<=n; i++) { head1[i] = head2[i] = -1; low[i] = 0; dfn[i] = 0; instack[i] = false; visit[i] = false; val[i] = 0; newval[i] = 0; dp[i] = 0; } } inline int min(int a, int b) { if(a < b) return a; else return b; } inline int max(int a, int b) { if(a>b) return a; else return b; } //建立原图 void addedge(int u, int v) { graph[cnt1].to = v; graph[cnt1].next = head1[u]; head1[u] = cnt1++; } //建立新图 void newaddedge(int u, int v) { newgraph[cnt2].to = v; newgraph[cnt2].next = head2[u]; head2[u] = cnt2++; } //强连通分支算法模板 void tarjan(int i) { int j, e; dfn[i] = low[i] = index++; instack[i] = true; stack[top++] = i; for(e = head1[i]; e!=-1; e=graph[e].next) { j = graph[e].to; if(!dfn[j]) { tarjan(j); low[i] = min(low[i], low[j]); } else if(instack[j]) low[i] = min(low[i], dfn[j]); } if(dfn[i] == low[i]) { num++; do { j = stack[--top]; instack[j] = false; belong[j] = num; }while(i!=j); } } //拓扑排序 void topsort(int x) { int i; visit[x] = true; for(i=head2[x]; i!=-1; i=newgraph[i].next) { int e = newgraph[i].to; if(!visit[e]) topsort(e); } tms[pt++] = x; } //建立新图的主程序 void buildgraph() { int i, j; for(i=0; i<n; i++) if(val[i]>0) newval[belong[i]] += val[i]; for(i=0; i<n; i++) for(j=head1[i]; j!=-1; j=graph[j].next) if(belong[i] != belong[graph[j].to]) { newaddedge(belong[i], belong[graph[j].to]); // printf("%d %d/n", belong[i], belong[graph[j].to]); } } void solve() { int i, j; for(i=0; i<n; i++) if(!dfn[i]) tarjan(i); buildgraph(); memset(visit, 0, sizeof(visit)); for(i=1; i<=num; i++) if(!visit[i]) topsort(i); for(i=0; i<pt; i++) { int w = tms[i], tmp = 0; dp[w] = newval[w]; for(j=head2[w]; j!=-1; j=newgraph[j].next) { tmp = max(tmp, dp[newgraph[j].to]); } dp[w] += tmp; } int ans = dp[1]; for(i=2; i<=num; i++) ans = max(ans, dp[i]); printf("%d/n", ans); } int main() { // freopen("in.txt", "r", stdin); int i; while(scanf("%d %d", &n, &m) != EOF) { init(); for(i=0; i<n; i++) scanf("%d", &val[i]); int u, v; for(i=0; i<m; i++) { scanf("%d %d", &u, &v); addedge(u, v); } solve(); } return 0; }  

你可能感兴趣的:(POJ_3160)