题目链接点这儿
给你一些课程,每个课程都分为多级。再给出你一些关系,如果你上了课i的level d1,那么你的课j的level 就提升至d2。这个提升的意思就是你可以上课j所有的level <= d2的课时。
问你有没有可能所有课程都达到最高级。
裸的最小树形图。。。课与课的关系是一些建边关系,另外就是因为你打到level d后,所有<= d的该门课你就都能上了,所以要再加上一些反向边。最后加一个连着每门课level0的一个源点,,,,跑一个最小树形图就完了。。。
交到hdu是0ms。。。。完全没有trick。。。
#include <iostream> #include <cstdio> #include <cstdlib> #include <vector> #include <cstring> using namespace std; typedef int type; const int inf = 1000; struct node { int s, e; type l; }; int sum[55]; node ed[500*50+2000+10]; int num; void add(int s, int e, type l) { ed[num].s = s; ed[num].e = e; ed[num].l = l; num++; } void init() { num = 0; sum[0] = 0; } int n, S; int pre[50*500+10], id[50*500+10], vis[50*500+10]; type in[50*500+10]; type Directed_MST(int root ,int NV , int NE){ type ret = 0 ; while(1){ for (int i = 0 ; i < NV ; i ++ )in[i] = inf ; for (int i = 0 ; i < NE ; i ++ ){ int s = ed[i].s ; int e = ed[i].e ; if(ed[i].l < in[e] && s != e){ pre[e] = s ; in[e] = ed[i].l ; } } for (int i = 0 ; i < NV ; i ++ ){ if(i == root)continue ; // printf("in[%d] = %d\n", i, in[i]); if(in[i] == inf)return -1 ; } int cntnode = 0 ; memset(vis ,-1, sizeof vis) ; memset(id ,-1, sizeof vis) ; in[root] = 0 ; for (int i = 0 ; i < NV ; i ++ ){ ret += in[i] ; int v = i ; while(vis[v] != i && id[v] == -1 && v != root){ vis[v] = i ; v = pre[v] ; } if(v != root && id[v] == -1){ for (int u = pre[v] ; u != v ; u = pre[u]){ id[u] = cntnode ; } id[v] = cntnode ++ ; } } if(cntnode == 0)break ; for (int i = 0 ; i < NV ; i ++ ){ if(id[i] == -1)id[i] = cntnode ++ ; } for (int i = 0 ; i < NE ; i ++ ){ int s = ed[i].s ; int e = ed[i].e ; ed[i].s = id[s] ; ed[i].e = id[e] ; if(ed[i].s != ed[i].e){ ed[i].l -= in[e] ; } } NV = cntnode ; root = id[root] ; } return ret ; } int a[55]; int main() { // freopen("1007.in", "r", stdin); // freopen("output.txt", "w", stdout); int n, m; while(scanf("%d%d", &n, &m) && n) { init(); for(int i = 0; i < n; i++) { scanf("%d", &a[i]); sum[i+1] = sum[i] + a[i]+1; } for(int i = 0; i < n; i++) { add(sum[n], sum[i], 0); for(int j = sum[i+1] - 1; j > sum[i]; j--) add(j, j-1, 0); } int c, l1, d, l2, cost; for(int i = 1; i <= m; i++) { scanf("%d%d%d%d%d", &c, &l1, &d, &l2, &cost); add(sum[c-1]+l1, sum[d-1]+l2, cost); } for(int i = 0; i < num; i++) printf("%d %d %d\n", ed[i].s, ed[i].e, ed[i].l); printf("%d\n", Directed_MST(sum[n], sum[n]+1, num)); } return 0; }