生成树模板总结

首先来发模板 poj 1287

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>

using namespace std;
const int maxn=1010;
const int INF=0x3f3f3f3f;
struct Node{
    double x,y,h;
}point[maxn];
double mat[maxn][maxn];
double h[maxn][maxn];
double l[maxn][maxn];
int n;
double head,tail;

double dist(Node &a,Node &b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double prim()
{
    double ans=0.0,Min;
    int vis[maxn];double dis[maxn];
    for(int i=0;i<n;i++){
        dis[i]=mat[0][i];
        vis[i]=0;
    }
    dis[0]=1;
    vis[0]=1;
    for(int l=1;l<n;l++){
        Min=INF;int pos=-1;
        for(int i=0;i<n;i++){
            if(!vis[i]&&dis[i]<Min){
                Min=dis[i];
                pos=i;
            }
        }
        vis[pos]=1;
        ans+=Min;
        for(int i=0;i<n;i++){
            if(!vis[i]&&dis[i]>mat[pos][i]){
                dis[i]=mat[pos][i];
            }
        }
    }
    return ans;
}
int main()
{
    int i,j;
    double maxc,minc,maxl,minl,mid;
    while(scanf("%d",&n)&&n)
    {
        maxc=-INF;
        minc=INF;
        maxl=-INF;
        minl=INF;
        for(i=0;i<n;i++)
        scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].h);
        for(i=0;i<n-1;i++)
        for(j=i+1;j<n;j++)
        {
            h[i][j]=h[j][i]=fabs(point[i].h-point[j].h);
            l[i][j]=l[j][i]=dist(point[i],point[j]);
            if(maxc<h[i][j])
            maxc=h[i][j];
            if(minc>h[i][j])
            minc=h[i][j];
            if(maxl<l[i][j])
            maxl=l[i][j];
            if(minl>l[i][j])
            minl=l[i][j];
        }
        head=minc/maxl;
        tail=maxc/minl;
        while(tail-head>1e-4)
        {
            mid=(head+tail)/2;
            for(i=0;i<n-1;i++)
            for(j=i+1;j<n;j++)
            mat[i][j]=mat[j][i]=h[i][j]-mid*l[i][j];
            if(prim()<=0.0)
            tail=mid;
            else
            head=mid;
        }
        printf("%.3f\n",head);
    }
    return 0;
}

然后来发次小生成树的模板 poj 1679

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>

using namespace std;
const int maxn=10010;
int f[maxn],mst[maxn];
int n,m,t;
struct V
{
    int u,v,l;
} a[maxn];

int sf(int x)
{
    return x==f[x]?f[x]:f[x]=sf(f[x]);
}

int cmp(V a,V b)
{
    return a.l<b.l;
}

void kruskal()
{
    int cnt=n-1;
    int ant=n-1;
    int res1=0;
    int res2=0;
    for(int i=0; i<=n; i++)f[i]=i;
    sort(a,a+m,cmp);
    for(int i=0; i<m&&ant; i++)
    {
        if(sf(a[i].u)!=sf(a[i].v))
        {
            f[sf(a[i].u)]=sf(a[i].v);
            res1+=a[i].l;
            ant--;
            mst[ant]=i;
        }
    }
    for(int i=0; i<n-1; i++)
    {
        ant=n-1;
        res2=0;
        for(int j=0; j<=n; j++)f[j]=j;
        for(int j=0; j<m&&ant; j++)
        {
            if(j==mst[i])continue;
            if(sf(a[j].u)!=sf(a[j].v))
            {
                f[sf(a[j].u)]=sf(a[j].v);
                res2+=a[j].l;
                ant--;
            }
        }
        //cout<<"2.---"<<ant<<"---"<<res2<<endl;
        if(ant!=0)continue;
        if(res1==res2){
            printf("Not Unique!\n");
            return;
        }
    }
    cout<<res1<<endl;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<m; i++)
            scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].l);
        kruskal();
    }
}

再来发最小树形图模板 Poj3164

/*
ID: CUGB-wwj
PROG:
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define INF 2000000000
#define MAXN 105
#define MAXM 1005
#define L(x) x<<1
#define R(x) x<<1|1
#define eps 1e-4
using namespace std;
typedef double type;
struct Point
{
    double x, y;
}p[MAXN];
struct node
{
    int u, v;
    type w;
}edge[MAXN * MAXN];
int pre[MAXN], id[MAXN], vis[MAXN], n, m;
type in[MAXN];
double dis(Point a, Point b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
type Directed_MST(int root, int V, int E)
{
    type ret = 0;
    while(true)
    {
        //1.找最小入边
        for(int i = 0; i < V; i++) in[i] = INF;
        for(int i = 0; i < E; i++)
        {
            int u = edge[i].u;
            int v = edge[i].v;
            if(edge[i].w < in[v] && u != v) {pre[v] = u; in[v] = edge[i].w;}
        }
        for(int i = 0; i < V; i++)
        {
            if(i == root) continue;
            if(in[i] == INF) return -1;//除了跟以外有点没有入边,则根无法到达它
        }
        //2.找环
        int cnt = 0;
        memset(id, -1, sizeof(id));
        memset(vis, -1, sizeof(vis));
        in[root] = 0;
        for(int i = 0; i < V; 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] = cnt;
                id[v] = cnt++;
            }
        }
        if(cnt == 0) break; //无环   则break
        for(int i = 0; i < V; i++)
            if(id[i] == -1) id[i] = cnt++;
              //3.建立新图
        for(int i = 0; i < E; i++)
        {
            int u = edge[i].u;
            int v = edge[i].v;
            edge[i].u = id[u];
            edge[i].v = id[v];
            if(id[u] != id[v]) edge[i].w -= in[v];
        }
        V = cnt;
        root = id[root];
    }
    return ret;
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        for(int i = 0; i < n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d", &edge[i].u, &edge[i].v);
            edge[i].u--;
            edge[i].v--;
            if(edge[i].u != edge[i].v) edge[i].w = dis(p[edge[i].u], p[edge[i].v]);
            else edge[i].w = INF; //去除自环
        }
        type ans = Directed_MST(0, n, m);
        if(ans == -1) printf("poor snoopy\n");
        else printf("%.2f\n", ans);
    }
    return 0;
}

最后是最小K度生成树

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<algorithm>
#include<climits>
using namespace std;
map<string,int> mp;
int m,n,k;
int g[30][30],dis[30],clo[30],pre[30],fst[30],max_side[30];
const int inf=1000010000;
struct node
{
    int v,cap;
    node(){}
    node(int _v,int _cap):v(_v),cap(_cap){}
    bool operator < (const node &dd) const
    {
        return cap>dd.cap;
    }
};
int prim(int src,int id)
{
    priority_queue<node> q;
    while(!q.empty()) q.pop();
    dis[src]=0;
    q.push(node(src,0));
    int ans=0;
    while(!q.empty())
    {
        node cur=q.top();
        q.pop();
        int u=cur.v;
        if(!clo[u])
        {
            clo[u]=id;
            ans+=dis[u];
            for(int i=1;i<n;i++)
            {
                if(!clo[i]&&g[u][i]!=0&&dis[i]>g[u][i])
                {
                    pre[i]=u;
                    dis[i]=g[u][i];
                    q.push(node(i,dis[i]));
                }
            }
        }
    }
    return ans;
}
void update(int cur,int last,int maxside)
{
    max_side[cur]=maxside>g[cur][last]?maxside:g[cur][last];
    for(int i=1;i<n;i++)
    {
        if(i!=last&&g[cur][i]!=0&&(pre[cur]==i||pre[i]==cur))
            update(i,cur,max_side[cur]);
    }
}
void solve()
{
    for(int i=0;i<n;i++)
    {
        dis[i]=inf;
        clo[i]=pre[i]=fst[i]=0;
    }
    int res=0,cnt=1;
    for(int i=1;i<n;i++)
    {
        if(!clo[i])
            res+=prim(i,cnt++);
    }
    for(int i=1;i<n;i++)
    {
        int id=clo[i];
        if(g[0][i]!=0&&(!fst[id]||g[0][i]<g[0][fst[id]]))
            fst[id]=i;
    }
    for(int i=1;i<cnt;i++)
    {
        res+=g[0][fst[i]];
        g[0][fst[i]]=g[fst[i]][0]=0;
        update(fst[i],0,0);
    }
    k=k-cnt+1;
    while(k--)
    {
        int tmp=0;
        for(int i=1;i<n;i++)//kdjfke
        {
            if(g[0][i]&&(tmp==0||max_side[tmp]-g[0][tmp]<max_side[i]-g[0][i]))
                tmp=i;
        }
        if(max_side[tmp]<=g[0][tmp])
            break;
        res=res-max_side[tmp]+g[0][tmp];
        g[0][tmp]=g[tmp][0]=0;
        int p=0;
        for(int i=tmp;pre[i]!=0;i=pre[i])
        {
            if(p==0||g[p][pre[p]]<g[i][pre[i]])
                p=i;
        }
        pre[p]=0;
        update(tmp,0,0);
    }
    printf("Total miles driven: %d\n",res);
}
int main()
{
    char s1[20],s2[20];
    int cap;
    while(scanf("%d",&m)!=EOF&&m!=0)
    {
        mp.clear();
        n=1;
        memset(g,0,sizeof(g));
        mp["Park"]=0;
        while(m--)
        {
            scanf("%s %s %d",s1,s2,&cap);
            if(!mp.count(s1)) mp[s1]=n++;
            if(!mp.count(s2)) mp[s2]=n++;
            int u=mp[s1],v=mp[s2];
            if(!g[u][v]||cap<g[u][v])
                g[u][v]=g[v][u]=cap;
        }
        scanf("%d",&k);
        solve();
    }
    return 0;
}
posted @ 2016-07-26 19:47  adfae  阅读(214)  评论(0编辑  收藏  举报