生成树

来源:互联网 发布:qq的网络传输协议 编辑:程序博客网 时间:2024/06/07 11:36


POJ 1639 最小度限制生成树 http://poj.org/problem?id=1639

#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<ctype.h>#include<algorithm>#include<stack>#include<queue>using namespace std;#define maxn 22int n,k;int e1[maxn][maxn];int e2[maxn][maxn];struct Edge{    int u,v,w;    Edge(int a,int b,int c){u=a,v=b,w=c;}    bool friend operator< (Edge a,Edge b){        return a.w>b.w;    }};priority_queue<Edge> q;char name[maxn][12];int l;char s1[12],s2[12];int get_id(char *p){    for(int i=0;i<l;i++){        if(strcmp(p,name[i])==0)            return i;    }    strcpy(name[l],p);    l++;    return l-1;}int bin[maxn];int find(int a){    if(bin[a]!=a) bin[a]=find(bin[a]);    return bin[a];}bool get(int a,int b){    int x=find(a);    int y=find(b);    if(x!=y) {bin[y]=x;return 1;}    return 0;}void dfs(int u,int fa){    for(int i=1;i<l;i++){        if(e2[u][i]==1&&i!=fa){            get(u,i);            dfs(i,u);        }    }}void Print_ans(){    int ans=0;    for(int i=0;i<l;i++)        for(int j=i+1;j<l;j++)            if(e2[i][j]==1)                ans+=e1[i][j];    printf("Total miles driven: %d\n",ans);}void solve(){    int cnt=0;    for(int i=0;i<=l;i++)  bin[i]=i;    while(!q.empty()){        Edge e=q.top();        q.pop();        if(get(e.u,e.v)){            if(e.u==0||e.v==0) cnt++;            e2[e.u][e.v]=e2[e.v][e.u]=1;        }    }    for(int i=0;i<=l;i++) bin[i]=i;    for(int j=1;j<l;j++){        if(e2[0][j]==1) dfs(j,0);    }    while(cnt>k){        int x,y,mmin=1000000;        for(int i=1;i<l;i++){            for(int j=i+1;j<l;j++){                if(e1[i][j]!=0&&e2[i][j]==0){                    int i1=find(i);                    int j1=find(j);                    if(i1==j1) continue;                    int mmax=max(e1[0][i1],e1[0][j1]);                    if(mmin>(e1[i][j]-mmax)){                        mmin=e1[i][j]-mmax;                        x=i; y=j;                    }                }            }        }        cnt--;        e2[x][y]=1,e2[y][x]=1;        int x1=find(x),y1=find(y);        if(e1[0][x1]>e1[0][y1]) e1[0][x1]=e1[x1][0]=0,get(y1,x1);        else e1[0][y1]=e1[y1][0]=0,get(x1,y1);    }    Print_ans();}void init(){    strcpy(name[0],"Park");    l=1;    memset(e1,0,sizeof(e1));    memset(e2,0,sizeof(e2));    while(!q.empty()) q.pop();    for(int i=0;i<n;i++){        int w;        scanf("%s%s%d",s1,s2,&w);        int d1=get_id(s1);        int d2=get_id(s2);        q.push(Edge(d1,d2,w));        e1[d1][d2]=e1[d2][d1]=w;    }    scanf("%d",&k);}int main(){    while(scanf("%d",&n)!=EOF){        init();        solve();    }}



HDU 2121最小树形图(无固定根) http://acm.hdu.edu.cn/showproblem.php?pid=2121

#include <iostream>#include <cstdio>#include <cmath>#include <vector>#include <cstring>#include <algorithm>#include <string>#include <set>#include <ctime>#include <queue>#include <map>#include <sstream>#define CL(arr, val)    memset(arr, val, sizeof(arr))#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))#define L(x)    (x) << 1#define R(x)    (x) << 1 | 1#define MID(l, r)   (l + r) >> 1#define Min(x, y)   x < y ? x : y#define Max(x, y)   x < y ? y : x#define E(x)    (1 << (x))const double eps = 1e-6;const double inf = ~0u>>1;typedef long long LL;using namespace std;const int N = 1100;   // 调整const int M = 20010;  // 调整struct node {  //可删    double x, y;} point[N];double SQ(int u, int v) {  // 可删    return sqrt((point[u].x - point[v].x)*(point[u].x - point[v].x) +                (point[u].y - point[v].y)*(point[u].y - point[v].y));}struct edg {    int u, v;    int cost;  //double} E[M];int In[N]; //doubleint ID[N];int vis[N];int pre[N];int NV, NE;  // n,m    0-->n-1  0-->m-1int Minroot;// 求入点int Directed_MST(int root) {  //double    int ret = 0;   //double    int i, u, v;    while(true) {        REP(i, NV)   In[i] = inf;        REP(i, NE) {    //找最小入边            u = E[i].u;            v = E[i].v;            if(E[i].cost < In[v] && u != v) {                In[v] = E[i].cost;                if(u==root) Minroot=i;     //求入口                pre[v] = u;            }        }        REP(i, NV) {    //如果存在除root以外的孤立点,则不存在最小树形图            if(i == root)   continue;            //printf("%.3lf ", In[i]);            if(In[i] == inf)    return -1;        }        int cnt = 0;        CL(ID, -1);        CL(vis, -1);        In[root] = 0;        REP(i, NV) {    //找环            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(u = pre[v]; u != v; u = pre[u]) {                    ID[u] = cnt;                }                ID[v] = cnt++;            }        }        if(cnt == 0)    break;        REP(i, NV) {            if(ID[i] == -1) ID[i] = cnt++;    //重新标号        }        REP(i, NE) {    //更新其他点到环的距离            v = E[i].v;            E[i].u = ID[E[i].u];            E[i].v = ID[E[i].v];            if(E[i].u != E[i].v) {                E[i].cost -= In[v];            }        }        NV = cnt;        root = ID[root];    }    return ret;}int main() {    while(scanf("%d%d",&NV,&NE)!=EOF)    {        int x=NE;        for(int i=0;i<NE;i++)            scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].cost);        for(int i=0;i<NV;i++){            E[NE].u=NV;            E[NE].v=i;            E[NE].cost=1e7;            NE++;        }        NV++;        int ans=Directed_MST(NV-1);        ans-=1e7;        if(ans>1e7) printf("impossible\n\n");        else printf("%d %d\n\n",ans,Minroot-x);  // Minroot-x 入口     }}/*无固定根的最小树形图 Sample Input3 1 0 1 1 4 4 0 1 100 2 10 1 3 20 2 3 30 Sample Outputimpossible 40 0      // 40权值和  0 入口*/


0 0
原创粉丝点击