poj1639 Picnic Planning

来源:互联网 发布:淘宝买家修改评论 编辑:程序博客网 时间:2024/05/03 21:30
#include <vector>#include <list>#include <map>#include <set>#include <queue>#include <deque>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <ctime>#include <cstring>#include <memory.h>using namespace std;/* * poj1639 AC  * K度最小生成树 * 1. 求出除去V0,其他每个森林的最小生成树(除去V0后,其他的点不一定都是连通的)。 * 2. 在每个森林中找出与V0距离最近的点,并与V0相连(此时即为一棵生成树,这棵 *    生成树的根结点为V0,即在与V0相连时,要修改前驱数组pre[])。 * 3. 循环 (度数 – 森林数)次,每次找到g[0][i] – MV[i]最小的i结点,其中MV[i] *    为Vi到V0的路径上不与V0相连的边的最大权值。 *    如果g[0][i] – MV[i] >= 0说明已经是最优解了,退出。 *    否则加入g[0][i]这条边,删去Vi到V0的路径上不与V0相连的最大权值的边。 * * 如何快速找到Vi到V0的路径上不与V0相连的边的最大权值? * MV[x] = max(MV[father],edge[i].c) (edge[i]为x到father的边,递推可得) * */int N,S,T;map<string,int> hash;struct EDGE{    int u,v,c,nm;}edge[1000];int head[25],next[1000],tot,goal;struct cmp{    bool operator()(const EDGE &t1,const EDGE &t2)    {        return t1.c>t2.c;    }};void addedge(int x,int y,int val){    edge[tot].u = x,edge[tot].v = y,edge[tot].c = val,edge[tot].nm = tot;    next[tot] = head[x],head[x] = tot++;}priority_queue<EDGE,vector<EDGE>,cmp> heap;bool vis[25],sel_e[1000];int solve(int x,int TT){    int E,nn,SUM;    while(!heap.empty()) heap.pop();    for(int i=head[x];i!=-1;i=next[i])        if(edge[i].v!=goal)            heap.push(edge[i]);    vis[x] = true,SUM = E = 0;     while(E<TT-1)    {        EDGE e = heap.top();        heap.pop();        if(vis[e.v]) continue;        sel_e[e.nm] = sel_e[e.nm^1] = true;        E++,SUM += e.c;        nn = e.v,vis[e.v] = true;        for(int i=head[nn];i!=-1;i=next[i])            if(edge[i].v!=goal && !vis[edge[i].v])                heap.push(edge[i]);    }    return SUM;}int col[25],C;int dfs(int x){    col[x] = C;    int ss = 1;    for(int i=head[x];i!=-1;i=next[i])        if(edge[i].v!=goal && !col[edge[i].v])            ss += dfs(edge[i].v);    return ss;}int MV[25],ne[25];void dfs_V(int x,int f){    for(int i=head[x];i!=-1;i=next[i])        if(sel_e[i] && edge[i].v!=f && edge[i].v!=goal)        {            if(MV[x]>edge[i].c)            {                MV[edge[i].v] = MV[x];                ne[edge[i].v] = ne[x];            }else            {                MV[edge[i].v] = edge[i].c;                ne[edge[i].v] = i;            }            dfs_V(edge[i].v,x);        }}int main(){    scanf("%d",&N);    char st[20],en[20];    T = tot = goal = 0;    memset(head,-1,sizeof(head));    hash.clear();    for(int i=1;i<=N;i++)    {        int k;        scanf("%s%s%d",st,en,&k);        if(!hash.count(st)) hash[st] = ++T;        if(!hash.count(en)) hash[en] = ++T;        if(!goal)        {            if(!strcmp(st,"Park")) goal = hash[st];            if(!strcmp(en,"Park")) goal = hash[en];        }        addedge(hash[st],hash[en],k);        addedge(hash[en],hash[st],k);    }    scanf("%d",&S);    int ans = 0;    C = 0;    memset(vis,false,sizeof(vis));    memset(col,0,sizeof(col));    memset(sel_e,false,sizeof(sel_e));    for(int i=1;i<=T;i++)        if(i!=goal && !col[i])            ++C,ans += solve(i,dfs(i));    int mi[25],me[25];    memset(mi,-1,sizeof(mi));    for(int i=head[goal];i!=-1;i=next[i])    {       int k = edge[i].v;       if(mi[col[k]]==-1 || edge[i].c<mi[col[k]])       {           mi[col[k]] = edge[i].c;           me[col[k]] = i;       }    }    for(int i=1;i<=C;i++)        ans += mi[i],sel_e[me[i]] = sel_e[me[i]^1] = true;        memset(MV,0,sizeof(MV));    for(int i=head[goal];i!=-1;i=next[i])        if(sel_e[i] && edge[i].v!=goal)            dfs_V(edge[i].v,goal);    for(int i=1;i<=S-C;i++)    {        int mm = 100000000,xx,ee,ww;        for(int j=head[goal];j!=-1;j=next[j])            if(!sel_e[j] && (mm==100000000 || mm>edge[j].c-MV[edge[j].v]))            {                mm = edge[j].c-MV[edge[j].v];                xx = edge[j].v,ee = j,ww = ne[edge[j].v];            }        if(mm>=0) break;        ans += mm;        sel_e[ee] = sel_e[ee^1] = true;        sel_e[ww] = sel_e[ww^1] = false;        MV[xx] = 0;        dfs_V(xx,goal);    }    printf("Total miles driven: %d\n",ans);    return 0;}

原创粉丝点击