没有上司的舞会

没有上司的舞会

(题目已略)

表示这种题目唯一的坑点就是输入。。居然是多组数据!

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn=6005;

class Graph{
public:
    struct Edge{
        int to, next; Graph *bel;
        void set(int x, int y, Graph *g){
            to=x; next=y; bel=g; }
        inline int operator *(){ return to; }
        Edge& operator ++(){
            return *this=bel->edge[next]; }
    };
    void reset(){ //edge不用清零,因为最后跳到的结点是0
        memset(fir, 0, sizeof(fir));
        cntedge=0; edge[cntedge].to=0;
    }
    void addedge(int x, int y){
        edge[++cntedge].set(y, fir[x], this);
        fir[x]=cntedge;
    }
    Edge& getlink(int x){ return edge[fir[x]]; }
private:
    int cntedge, fir[maxn];
    Edge edge[maxn*2];
};

Graph g;
int n, root, hap[maxn], visit[maxn];
int f[maxn][2];

void dfs(int now, int par){
    Graph::Edge e=g.getlink(now);
    visit[now]=1; f[now][1]+=hap[now];
    for (; *e; ++e){
        if (*e==par) continue; dfs(*e, now);
        f[now][0]+=max(f[*e][0], f[*e][1]);
        f[now][1]+=f[*e][0];
    }
}

//以后处理树的时候,注意怎么把森林连起来!不应该看入度出度!

int main(){
    while (~scanf("%d", &n)){
        g.reset(); memset(visit, 0, sizeof(visit));
        memset(f, 0, sizeof(f));
        for (int i=1; i<=n; ++i) scanf("%d", &hap[i]);
        int x, y; scanf("%d%d", &x, &y);
        while (x&&y){
            g.addedge(x, y); g.addedge(y, x);
            scanf("%d%d", &x, &y);
        }
        int ans=0;
        for (int i=1; i<=n; ++i)
            if (!visit[i]){
                dfs(i, 0);
                ans+=max(f[i][0], f[i][1]);
            }
        printf("%d
", ans);
    }
    return 0;
}