一个国王,他拥有一个国家。最近他因为国库里钱太多了,要征集一只部队要保卫国家。他选定了N个女兵和M个男兵,但事实上每征集一个兵他就要花10000RMB,即使国库里钱再多也伤不起啊。他发现,某男兵和某女兵之间有某种关系,这种关系可以使KING少花一些钱就可以征集到兵,不过国王也知道,在征兵的时候,每一个兵只能使用一种关系来少花钱。这时国王向你求助,问他最少要花多少的钱。
读入(conscription.in)
第一行:T,一共T组数据。
接下来T组数据,
第一行包括N,M,R
接下来的R行 包括Xi,Yi,Vi 表示如果招了第Xi个女兵,再招第Yi个男兵能省Vi元(同样表示如果招了第Yi个男兵,再招第Xi个女兵能也省Vi元)
输出(conscription.out)
共T行,表示每组数据的最终花费是多少(因为国库里的钱只有2^31-1,所以保证最终花费在maxlongint范围内)
这题是一道最小生成树的题 其实题目说的有点不太清楚 每个人只能用一种关系来少花钱 如果说一个人”被依赖“或”依赖别人“少花钱后这两人都不能利用关系了 这样的话很容易想到二分图匹配 写了半天最大流发现用二分图做也不会 而且数据太大 但题目的意思其实是每个人用”别人“来少花钱 而对方不受影响 那么一共有n+m个人 我们选n+m-1条边 也就是关系 因为第一个人被征用时没有人在队伍里 他不能利用任何关系 这样一来就是最小生成树 或者说最大生成树了 还要注意联通性问题 如果不连通 那么选不了n+m-1那么多条边 尽量多选就行了
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<algorithm> 5 #define LL long long 6 using namespace std; 7 const int maxn=20010; 8 struct Edge{ 9 LL from,to,dist; 10 bool operator<(const Edge& rhs)const{ 11 return dist<rhs.dist; 12 } 13 }; 14 LL n,m,r,fa[maxn],x,y,z; 15 vector<Edge> edges; 16 void init(){ 17 for(int i=1;i<=n+m;i++) fa[i]=i; 18 edges.clear(); 19 } 20 LL find(LL x){ 21 if(fa[x]==x) return x; 22 return fa[x]=find(fa[x]); 23 } 24 int main(){ 25 freopen("conscription.in","r",stdin); 26 freopen("conscription.out","w",stdout); 27 int T; 28 scanf("%d",&T); 29 while(T--){ 30 scanf("%lld%lld%lld",&m,&n,&r); 31 init(); 32 for(int i=1;i<=r;i++){ 33 scanf("%lld%lld%lld",&x,&y,&z); 34 edges.push_back((Edge){m+x+1,y+1,-z}); 35 } 36 sort(edges.begin(),edges.end()); 37 LL ans=0; 38 for(int i=0;i<edges.size();i++){ 39 Edge& e=edges[i]; 40 LL a=find(e.from),b=find(e.to); 41 if(a==b) continue; 42 ans+=e.dist; 43 fa[a]=b; 44 } 45 printf("%lld\n",10000*(n+m)+ans); 46 } 47 fclose(stdin); 48 fclose(stdout); 49 return 0; 50 }
时间: 2024-10-09 02:20:09