HDU-5438 dfs+拓扑排序+前向星

题目传送门: http://acm.hdu.edu.cn/showproblem.php?pid=5438


题目大意:有n个水池,m个管道,每个水池都有一个权值,Betty想要拆水池,只能拆度数为一的水池,他将一直拆下去直到不能拆为止,求含奇数个水池的连通图的总权值


思路:先用前向星建图,然后用类似拓扑排序的方式将可以拆的水池找出来,最后跑一遍dfs将有奇数个点的连通图给找出来


代码如下:

#include
using namespace std;

#define   lowbit(x)     x&(-x)
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   ll            long long
#define   ull           unsigned long long
#define   mem(n,v)      memset(n,v,sizeof(n))
#define   MAX           1000005
#define   MAXN          2000005
#define   PI            3.1415926
#define   E             2.718281828459
#define   opnin         freopen("text.in.txt","r",stdin)
#define   opnout        freopen("text.out.txt","w",stdout)
#define   clsin         fclose(stdin)
#define   clsout        fclose(stdout)

const int    INF    =   0x3f3f3f3f;
const ll     INFF   =   0x3f3f;
const double pi     =   3.141592653589793;
const double inf    =   1e18;
const double eps    =   1e-8;
const ll     mod    =   1e9+7;
const ull    mx     =   133333331;

struct e
{
    int next;
    int to;
    int v;
}edge[MAXN];
int d[MAXN];
int head[MAXN];
int val[MAXN];
int vis[MAXN];
ll sum,Count,cnt;
int n,m;
void init()
{
    mem(val,0);
    mem(vis,0);
    mem(head,-1);
    mem(d,0);
    cnt = sum = Count = n = m = 0;
}
void makeedge(int u,int v)
{
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}
void getmap(int m)
{
    int x,y;
    int cnt = 1;
    for(int i=1;i<=m;i++){
        scanf("%d %d",&x,&y);
        d[x]++;
        d[y]++;
        makeedge(x,y);
        makeedge(y,x);

    }

}
void toposort()
{
    queueq;
    for(int i=1;i<=n;i++){
        if(d[i] == 1) q.push(i);
    }
    while(!q.empty()){
        int id = q.front();
        q.pop();
        d[id] = 0;
        for(int i=head[id];i != -1;i = edge[i].next){
            d[edge[i].to]--;
            if(d[edge[i].to] == 1) q.push(edge[i].to);
        }
    }
}
void dfs(int id)
{
    vis[id] = 1;
    sum += val[id];
    Count++;
    for(int i=head[id];i != -1;i = edge[i].next){
        if(!vis[edge[i].to] && d[edge[i].to] > 1) dfs(edge[i].to);
    }
}
void solve()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&val[i]);
    }
    getmap(m);
    toposort();
    ll ans = 0;
    for(int i=1;i<=n;i++){
        if(!vis[i] && d[i] > 1) dfs(i);
        if(Count & 1) ans += sum;
        sum = 0;
        Count = 0;
    }
    cout << ans << endl;
}

int main()
{
    int kace;
    cin >> kace;
    while(kace--){
        init();
        solve();
    }
}


你可能感兴趣的:(ACM/ICPC)