并查集&最小生成树

 

 Minimal Ratio Tree

  dfs+prim

#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include<cstdio>
#include <cstring>
#include <queue>
#include<bitset>
typedef long long ll;

using namespace std;
const double inf=2000001.0;

int m,n;
double mi,v,u;
double  node[100],e[100][100];
int vis[100],vis2[100],vis3[100];
double d[100];

double prim()
{
    fill(d,d+100,inf);
    fill(vis2,vis2+100,0);
    int flag;
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==1)
        {
            flag=i;
            break;
        }
    }
    d[flag]=0.0;
    double ans=0,sv=0;
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==1)
        {
            sv+=node[i];
        }
    }
    for(int i=1;i<=n;i++)
    {
        int u=-1;
        double mi=inf;
        for(int j=1;j<=n;j++)
        {
            if(vis[j]==1&&vis2[j]==0&&d[j]<mi)
            {
                u=j;
                mi=d[j];
            }
        }
        if(u==-1)
            break;
        vis2[u]=1;
        ans+=d[u];
        for(int v=1;v<=n;v++)
        {
            if(vis[v]==1&&vis2[v]==0&&e[u][v]<d[v])
                d[v]=e[u][v];
        }
    }
    //cout<<ans<<' '<<sv<<endl;
    return ans/sv;
}

void dfs(int x,int num)
{
    if(x>n+1)
        return ;
    if(num>m)
        return ;
    if(num==m)
    {
        //for(int i=1;i<=n;i++)
           // cout<<vis[i]<<' ';
        //cout<<endl;
        double ans=prim();
       //cout<<ans<<endl;
        if(ans<mi)
            {
                mi=ans;
                memcpy(vis3, vis2, sizeof(vis2));
            }
        return ;
    }
    vis[x]=1;
    dfs(x+1,num+1);
    vis[x]=0;
    dfs(x+1,num);
}

int main()
{
    while(scanf("%d%d",&n,&m)&&n&&m)
    {
        mi=inf;
        fill(vis,vis+n+1,0);
        for(int i=1;i<=n;i++)
            scanf("%lf",&node[i]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%lf",&e[i][j]);
    dfs(1,0);
    //cout<<mi<<endl;
    int flag=0;
    for(int i=1;i<=n;i++)
    {
        if(vis3[i]!=0&&flag==1)
            cout<<' '<<i;
        if(!flag&&vis3[i]!=0)
            {
                cout<<i;
                flag=1;
            }

    }
    cout<<endl;
    }
    return 0;
}

HDU5253(最小生成树)连接管道

#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include<cstdio>
#include <cstring>
#include <queue>
#include<bitset>
typedef long long ll;

using namespace std;
const int inf=2*1e6;


int n,m;
int G[1001][1001],f[800000];

struct edge
{
    int u,v,c;
}e[2000005];

bool cmp(edge a,edge b)
{
    return a.c<b.c;
}


int find(int x)
{
    if(x==f[x]) return x;
    else return f[x]=find(f[x]);
}


int kru(int n,int m)
{
    int ans,num;
    ans=0,num=0;
    for(int i=0;i<n;i++)
        f[i]=i;
    for(int i=0;i<m;i++)
    {
        int fa=find(e[i].u);
        int fb=find(e[i].v);
        if(fa!=fb)
        {
            f[fa]=fb;
            ans+=e[i].c;
            num++;
            if(num==n-1)
                break;
        }

    }
    return ans;
}

int main()
{
    int q;
    scanf("%d",&q);
    int flag=1;
    while(q--)
    {
      scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
        {
            scanf("%d",&G[i][j]);
        }
        int cnt=0;
        for(int i=0;i<n;i++)
         {
             for(int j=0;j<m;j++)
             {
                 int t=i*m+j;
                 if(i!=n-1)
                 {
                     e[cnt].u=t;
                     e[cnt].v=t+m;
                     e[cnt].c=abs(G[i][j]-G[i+1][j]);
                     cnt++;
                 }
                  if(j!=m-1)
                 {
                     e[cnt].u=t;
                     e[cnt].v=t+1;
                     e[cnt].c=abs(G[i][j]-G[i][j+1]);
                     cnt++;
                 }
             }
         }
         sort(e,e+cnt,cmp);
         /*for(int i=0;i<cnt;i+=2)
            cout<<e[i].u<<' '<<e[i].v<<' '<<e[i].c<<endl;
         cout<<endl;*/
         int ans=kru(n*m,cnt);
         printf("Case #%d:\n",flag);
         flag++;
         printf("%d\n",ans);
    }
    return 0;
}

 

HDU 4463 Outlets (确定一条边的裸树)

#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include<cstdio>
#include <cstring>
#include <queue>
#include<bitset>
typedef long long ll;

using namespace std;
const int inf=2*1e6;


int n,m;
int G[1001][1001],f[800000],vis[5555],t;
int p,q;


struct node
{
    int x,y;
}no[100];

struct edge
{
    int u,v;
    double c;
}e[20005];

bool cmp(edge a,edge b)
{
    return a.c<b.c;
}


int find(int x)
{
    if(x==f[x]) return x;
    else return f[x]=find(f[x]);
}


double kru(int n,int m)
{
    int num;
    double ans=0;
    num=0;
    for(int i=0;i<n;i++)
        f[i]=i;
    for(int i=0;i<m;i++)
    {
        int fa=find(e[i].u);
        int fb=find(e[i].v);
        if(fa!=fb)
        {
            f[fa]=fb;
            //cout<<e[i].c<<endl;
            ans+=e[i].c;
            num++;
            if(num==n-1)
                break;
        }

    }
    return ans;
}
double dis(node a,node b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main()
{
    while(scanf("%d",&n)&&n)
    {
        cin>>p>>q;
        p--,q--;
        for(int i=0;i<n;i++)
            cin>>no[i].x>>no[i].y;
        e[0].u=p;
        e[0].v=q;
        e[0].c=dis(no[p],no[q]);
        int cnt=1;
        for(int i=0;i<n-1;i++)
        {
            for(int j=i;j<n;j++)
            {
                if(i==q&&j==p)
                    continue;
                if(i==p&&j==q)
                    continue;
                e[cnt].u=i;
                e[cnt].v=j;
                e[cnt].c=dis(no[i],no[j]);
                cnt++;
            }
        }
        sort(e+1,e+cnt+1,cmp);
        double ans=kru(n,cnt+1);
        printf("%.2lf\n",ans);
    }
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值