uoj51(最小生成樹+揹包+bitset)

Description
兔紙王國中有 NN 個城市,第 ii 個城市和第 jj 個城市的距離是 Di,jDi,j (保證Di,j=Dj,i且Di,i=0Di,j=Dj,i且Di,i=0) 。

兔紙們使用兩種蘿蔔來修路,分別是富含胡蘿蔔素的蘿蔔和富含維生素CC的蘿蔔,單價分別是P1,P2P1,P2。由於經濟蕭條,所以兩種蘿蔔的上限分別是Q1,Q2Q1,Q2。

現在兔紙們希望修建若干條道路,使得任意兩個城市聯通。既然經濟蕭條的話,它們希望知道最小的總費用。顯而易見的,兔紙們是不會同意一條道路上存在兩種蘿蔔的。

Input Specification
第 11 行, 11 個整數 NN。

第 22 行到第 N+1N+1 行, NN 個整數Di,jDi,j。

第 N+2N+2 行, 44 個整數 P1,P2,Q1,Q2P1,P2,Q1,Q2 。

Output Specification
第 11 行, 11 個整數, 表示最小的總費用。無解則輸出 -1 。

Input and Output Sample
[input 1]
2
0 2
2 0
2 3 1 3

[output 1]
6

[input 2]
3
0 1 3
1 0 2
3 2 0
1 2 5 0

[output 2]
3
Extra Input Sample

Extra Output Sample

Data Restriction
對於 30% 的數據, 1≤N≤51≤N≤5。
對於 60% 的數據, 1≤N≤201≤N≤20。

對於 100% 的數據, 1≤N≤1,000,∀i≠j:1≤Di,j≤1,000,0≤P1,P2,Q1,Q2≤1,000,0001≤N≤1,000,∀i≠j:1≤Di,j≤1,000,0≤P1,P2,Q1,Q2≤1,000,000。


【思路】先找出最短路,然後用揹包,用bitset可以省時間和空間,其中f[ i ]表示是否有和爲i的方案

【代碼】

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#define ll long long
#define maxn 1003
#define inf 10000000000013
using namespace std;
bitset<1000006>f;
struct data{
    int u,v;ll d;
    bool operator<(const data&b)const{
	    return d<b.d;
	}
}e[maxn*maxn];
int n,q1,q2,p1,p2,cnt=0,fa[maxn];
ll w[maxn],sum=0,ans;
int get(){
    char c;while(!isdigit(c=getchar()));
	int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
	return v;	
}
void init(){
    n=get();ll x;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j){
		    x=get();
		    if(j>i){
			    e[++cnt].u=i;
			    e[cnt].v=j;
			    e[cnt].d=x;
			}
		}
	q1=get(),q2=get(),p1=get(),p2=get();
	sort(e+1,e+1+cnt);
}
int getfa(int x){
    if(fa[x]==x)return fa[x];
    else return (fa[x]=getfa(fa[x]));
}
void solveit(){
	int t=0;f[0]=1;
	for(int i=1;i<=n;++i)fa[i]=i;
    for(int i=1;i<=cnt;++i){
	    int x=getfa(e[i].u),y=getfa(e[i].v);
	    if(x!=y){
		    f|=f<<e[i].d;     //巧妙地位運算
		    sum+=e[i].d;
		    fa[x]=y;
		    --n;
		}
		if(n==1)break;
	}
	ans=(ll)inf;
	for(int i=0;i<=p1;++i){
	    if(f[i] && (sum-i)<=p2)ans=min(ans,(ll)i*(ll)q1+(ll)(sum-i)*(ll)q2);
	}
       if(ans==(ll)inf)printf("-1\n");
	else printf("%lld\n",ans);
}
int main(){
    init();
    solveit();
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章