其他分享
首页 > 其他分享> > Joining Capitals (斯坦纳树)

Joining Capitals (斯坦纳树)

作者:互联网

最小斯坦纳树:

基本模板:

【模板】最小斯坦纳树 (洛谷)

#include <bits/stdc++.h>
using namespace std;
#define ri register int 
#define M 105

template <class G> void read(G &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return ;
}

struct dian{
    int val,to;
};
vector <dian> p[M];
int n,m,T;
int dp[M][1<<11];
int k[M];
int dis[M];
struct cmp
{
    bool operator ()(const int a,const int b)const 
    {
        return dis[a]>dis[b];
    }
};
int vis[M];
void dj(int s)
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    priority_queue<int,vector<int>,cmp> q;
    for(ri i=1;i<=n;i++)
    {
        if(dp[i][s]<dis[i])
        {
            dis[i]=dp[i][s];
            q.push(i);
        }
    }
    while(!q.empty())
    {
        while(!q.empty()&&vis[q.top()]) q.pop();
        int a=q.top(); if(q.empty()) break;
        vis[a]=1;
        for(ri i=0;i<p[a].size();i++)
        {
            int b=p[a][i].to;
            if(dis[b]>dis[a]+p[a][i].val)
            {
                dis[b]=dis[a]+p[a][i].val;
                q.push(b);
            }
        }
    }
    for(ri i=1;i<=n;i++)
    {
        dp[i][s]=dis[i];
    //    printf("%d\n",dis[i]);
    }
}
int main(){
    
    read(n);read(m);read(T);
    
    for(ri i=1;i<=m;i++)
    {
        dian t;int a,b,c;
        read(a);read(b);read(t.val);
        t.to=b;
        p[a].push_back(t);
        t.to=a;
        p[b].push_back(t);
    }
    
    memset(dp,0x3f,sizeof(dp));
    for(ri i=1;i<=T;i++)
    {
        read(k[i]);
        dp[k[i]][1<<(i-1)]=0;
    }
    for(ri s=1;s<(1<<T);s++)
    {
        for(ri i=1;i<=n;i++)
        {
            for(ri sur=s&(s-1);sur;sur=s&(sur-1))
            {
                dp[i][s]=min(dp[i][s],dp[i][sur]+dp[i][s^sur]);
            }
        }
        dj(s);
    }
    int ans=dp[0][0];//printf("%d\n",ans);
    for(ri i=1;i<=n;i++) ans=min(ans,dp[i][(1<<(T))-1]);
    printf("%d",ans);
    return 0;
    
}
 
View Code

 

本题:Gym - 101908J

A far far away kingdom has NN cities, among which KK are capitals. King Richard wants to build transmission lines, each one directly connecting two cities. Also, there needs to be a path, i.e. a sequence of transmission lines, between any pair of capitals.

Each transmission line has an associated cost, which is the Euclidean distance between the two cities that the transmission line connects. As the king is greedy, he wishes that the transmission lines are set up so that the total cost (sum of the costs for each line) is kept as small as possible.

The figure A shows an example of a kingdom with N = 10N=10 cities and K = 4K=4 capitals. The Chief Engineer reported to the king the solution shown in figure B. Such solution, in fact, minimizes the total cost. But the king didn't like to see a capital with more than one transmission line. He then determined a new restriction: a capital can be connected to only one other city. That way, after working a lot, Chief Engineer presented the new solution, illustrated in figure C. He's just not so sure if this is the optimal solution, so he needs your help.


Given the coordinates of the cities, your program should compute the smallest total cost to build transmission lines so that every pair of capitals is connected by a sequence of transmission lines and every capital is directly connected to only one city.

Input
The first line of the input contains two integers N, KN,K (4 \leq N \leq 1004≤N≤100; 3 \leq K < \min(10, N))3≤K<min(10,N)), indicating respectively the number of cities and the number of capitals. The following NN lines contain two integers XX and YY each (−1000 \leq X, Y \leq 1000−1000≤X,Y≤1000), representing the coordinates of a city. The KK first cities are the capitals. There are no two cities with the same coordinates.

Output
Print a line containing a real number, with 5 decimal places, indicating the smallest total cost to build transmission lines, according to the restrictions above.
View problem

思路:

#include <bits/stdc++.h>
using namespace std;
#define ri register int 
#define M 105

template <class G> void read(G &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return ;
}

struct dian{
    int to;double val;
};
vector <dian> p[M];
int n,m,T;
double dp[M][(1<<11)+5];
double dis[M];
struct cmp
{
    bool operator ()(const int a,const int b)const 
    {
        return dis[a]>dis[b];
    }
};
int vis[M];
void dj(int s)
{
    for(ri i=1;i<=n;i++) dis[i]=1e9;
    memset(vis,0,sizeof(vis));
    priority_queue<int,vector<int>,cmp> q;
    for(ri i=1;i<=n;i++)
    {
        if(dp[i][s]<dis[i])
        {
            dis[i]=dp[i][s];
            q.push(i);
        }
    }
    while(!q.empty())
    {
        while(!q.empty()&&vis[q.top()]) q.pop();
        int a=q.top(); if(q.empty()) break;
        vis[a]=1;
        for(ri i=0;i<p[a].size();i++)
        {
            int b=p[a][i].to;
            if(b<=T) continue; 
            if(dis[b]>dis[a]+p[a][i].val)
            {
                dis[b]=dis[a]+p[a][i].val;
                q.push(b);
            }
        }
    }
    for(ri i=1;i<=n;i++)
    {
        dp[i][s]=dis[i];
    //    printf("%d\n",dis[i]);
    }
}
struct dn{
    double x,y;
}node[M];
double get(int a,int b)
{
    return sqrt((node[a].x-node[b].x)*(node[a].x-node[b].x)+(node[a].y-node[b].y)*(node[a].y-node[b].y));
}
int main(){
    
    read(n);read(T);
    
    for(ri i=1;i<=n;i++)
    {
        cin>>node[i].x>>node[i].y;
    }
    for(ri i=1;i<=T;i++)
    {
        for(ri j=T+1;j<=n;j++)
        {
            double a=get(i,j);
            dian t;
            t.to=j;t.val=a;
            p[i].push_back(t);
            t.to=i;
            p[j].push_back(t);
        }
    }
    for(ri i=T+1;i<=n;i++)
    {
        for(ri j=T+1;j<=n;j++)
        {
            if(i==j) continue;
            double a=get(i,j);
            dian t;
            t.to=j;t.val=a;
            p[i].push_back(t);
            t.to=i;
            p[j].push_back(t);
        }
    }
   for(ri i=0;i<=n;i++)
   for(ri s=0;s<=(1<<T);s++)
   dp[i][s]=1e9;
    for(ri i=1;i<=T;i++)
    {
        dp[i][1<<(i-1)]=0;
    }
    for(ri s=1;s<(1<<T);s++)
    {
        for(ri i=1;i<=n;i++)
        {
            for(ri sur=s&(s-1);sur;sur=s&(sur-1))
            {
                dp[i][s]=min(dp[i][s],dp[i][sur]+dp[i][s^sur]);
            }
        }
        dj(s);
    }
    double ans=dp[0][0];
    for(ri i=1;i<=n;i++) ans=min(ans,dp[i][(1<<(T))-1]);//
    printf("%0.5lf",ans);
    return 0;

}
 
View Code

后记:

 

标签:ch,int,Capitals,节点,斯坦纳,transmission,ri,dp,Joining
来源: https://www.cnblogs.com/Lamboofhome/p/16195306.html