POJ3538 Domestic Networks DP+MST

52 篇文章 0 订阅
7 篇文章 0 订阅
本文介绍了一个使用动态规划和最小生成树算法解决的问题:如何在给定的公寓间连接方案中,利用有限数量的不同类型的电缆(5号和6号),以最低的成本完成所有公寓的网络连接。文章提供了一种有效的方法来确定最优电缆分配方案。
摘要由CSDN通过智能技术生成

简单DP

DP之前先求一个最小生成树

状态转移

f[i][j]  表示前i条边用了j单位的5号材料所用的最小花费

f[i][j]=min(f[i][j],f[i-1][j-len]+len*c5)

f[i][j]=min(f[i][j],f[i-1][j]+len*c6)

然后回溯输出解就可以了

内存有点吃紧要用滚动数组



Domestic Networks
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 625 Accepted: 174 Special Judge

Description

Alex is a system administrator of Domestic Networks Inc. His network connects apartments and spans over multiple buildings.

The network expands and Alex has to design a new network segment. He has a map that shows apartments to connect and possible links. Each link connects two apartments and for each possible link its length is known. The goal is to make all apartments connected (possibly through other apartments).

Domestic Networks Inc. buys cable in the nearest cable shop. Unfortunately, shop sells only category 5 and 6 cables at price of p5 and p6 rubles per meter respectively. Moreover, there are only q5meters of category 5 cable and q6 meters of category 6 cable available in the shop.

Help Alex to solve a hard problem: make a new network construction plan with possible minimal cost. A plan consists of list of links to be made and cable category for each link (each link should be a single piece of cable of either 5 or 6 category). The cost of the plan is the sum of cost of all cables. The total length of cables of each category used in the plan should not exceed the quantity of the cable available in the shop.

Input

The first line of the input file contains two numbers: n — the number of apartments to be connected and m — the number of possible links (1 ≤ n ≤ 1000, 1 ≤ m ≤  10 000 ).

Following m lines contain possible link descriptions. Each description consists of three integer numbers: ai and bi — apartments that can be connected by the link and li — link length in meters (0 ≤ li ≤ 100). Apartments are numbered from 1 to n.

The last line of the input file contains four integer numbers: p5q5p6 and q6 — price and quantity of category 5 and 6 cables respectively (1 ≤ piqi ≤  10 000 ).

Output

If all apartments can be connected with the available cable, output n lines — an optimal network construction plan. The first line of the plan must contain plan’s cost. Other lines of the plan must consist of two integer numbers each: ai — number of the link to make and ci — the category of the cable to make it of. Links are numbered from 1 to m in the order they are specified in the input file. If there are more than one optimal plans, output any of them.

If there is no plan meeting all requirements, output a single word “Impossible”.

Sample Input

6 7
1 2 7
2 6 5
1 4 8
2 3 5
3 4 5
5 6 6
3 5 3
2 11 3 100

Sample Output

65
1 5
2 6
4 6
5 6
7 5
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 1010
struct edge
{
    int id;
	int s,e;
	int dis;
};

struct sel
{
    int id;
    int dis;
}l[MAXN];

edge e[12000];
int  set[MAXN];
int n,m;
int p1,p2,q1,q2;
int top;

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

void init(int n)
{
	for(int i=0;i<=n;i++) set[i]=i;
}

int find(int a)
{

	int root=a;
	int temp;
	while(set[root]!=root)
		root=set[root];
	while(set[a]!=root)
	{
		temp=a;
		a=set[a];
		set[temp]=root;
	}
	return root;
}

bool merge(int a,int b)
{
	int x=find(a);
	int y=find(b);
	if(x==y)
		return false;
	set[x]=y;
	return true;
}

int kruscal()
{
	int num=0,sum=0;
	top=0;
	for(int i=0;i<m && num<n-1;i++)
	{
		if(merge(e[i].s,e[i].e))
		{
			sum+=e[i].dis;
			l[top].id=e[i].id;
			l[top++].dis=e[i].dis;
			num++;
		}
	}
	if(num!=n-1) return -1;
	return sum;
}

long long dp[2][10105];
int path[MAXN][10105];

void dfs(int cnt,int y)
{
    if(!cnt) return;
    if(path[cnt][y]!=y)
    {
        dfs(cnt-1,path[cnt][y]);
        printf("%d 5\n",l[cnt-1].id);
    }
    else
    {
        dfs(cnt-1,y);
        printf("%d 6\n",l[cnt-1].id);
    }
}

bool cmp2(sel a,sel b)
{
    return a.id<b.id;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        init(n);
        int dis;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&e[i].s,&e[i].e,&e[i].dis);
            e[i].id=i+1;
        }
        sort(e,e+m,cmp);
        scanf("%d%d%d%d",&p1,&q1,&p2,&q2);
        if((dis=kruscal())==-1 ||dis>q1+q2)
            printf("Impossible\n");
        else
        {
            int total=0;
            sort(l,l+top,cmp2);
            for(int i=0;i<=q1;i++)
                dp[0][i]=dp[1][i]=INF;
            dp[0][0]=0;
            int cur=0;
            for(int i=1;i<=top;i++)
            {
                total+=l[i-1].dis;
                int c=l[i-1].dis;
                for(int j=q1;(j>=c||total-j<=q2)&&j>=0;j--)
                {
                    if(total-j<=q2&&dp[cur][j]!=INF&&dp[cur][j]+c*p2<dp[cur^1][j])
                    {
                        dp[cur^1][j]=dp[cur][j]+c*p2;
                        path[i][j]=j;
                    }
                    if(j>=c&&dp[cur][j-c]!=INF&&dp[cur][j-c]+c*p1<dp[cur^1][j])
                    {
                        dp[cur^1][j]=dp[cur][j-c]+c*p1;
                        path[i][j]=j-c;
                    }

                }
                for(int j=q1;j>=0;j--) dp[cur][j]=INF;
                cur=cur^1;
            }
            long long ans=INF,y=-1;
            for(int i=0;i<=q1;i++)
            {
                if(ans>dp[cur][i])
                {
                    ans=dp[cur][i];
                    y=i;
                }
            }
            if(ans==INF)
                printf("Impossible\n");
            else{
                printf("%lld\n",ans);
                dfs(top,y);
            }
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值