A Birthday (網路流 花費和流量有關)
阿新 • • 發佈:2018-12-15
POINT:
這題本質上就是一個網路流。但它的邊的花費是流量的平方。
我們可以對每個點對,增加幾條邊,花費分別為1,3,5,7,9.容量為1.
這樣就實現了花費為流量的平方。
#include <bits/stdc++.h> using namespace std; #define LL long long typedef pair<int,int> pr; const int maxn =5000; const int inf = 0x3f3f3f3f; struct node { int x,y; }; int s,t; struct edge { int from,to,cap,flow,cost; edge(int u,int v,int c,int f,int dd): from(u),to(v),cap(c),flow(f),cost(dd){} }; vector<int>G[maxn]; vector<edge>len; void add(int u,int v,int cap,int cost) { len.push_back(edge(u,v,cap,0,cost)); len.push_back(edge(v,u,0,0,-cost)); G[u].push_back(len.size()-2); G[v].push_back(len.size()-1); } bool spfa(int &ans) { int dis[maxn],pre[maxn],inq[maxn]; for(int i=1;i<=t;i++) dis[i]=inf; memset(inq,0,sizeof inq); memset(pre,-1,sizeof pre); dis[0]=0; pre[0]=0; inq[0]=1; int a=inf; queue<int> q; q.push(0); while(!q.empty()) { int u=q.front();q.pop();inq[u]=0; for(int i=0;i<G[u].size();i++) { edge e = len[G[u][i]]; if(e.cap>e.flow&&dis[e.to]>dis[u]+e.cost) { dis[e.to]=dis[u]+e.cost; a=min(a,e.cap-e.flow); pre[e.to]=G[u][i]; if(!inq[e.to]) { q.push(e.to); inq[e.to]=1; } } } } if(dis[t]==inf) return 0; ans+=dis[t]; int u=t; while(u!=s) { len[pre[u]].flow+=a; len[pre[u]^1].flow-=a; u=len[pre[u]].from; } return 1; } int mincost() { int cost=0; while(spfa(cost)) { } return cost; } //void add(int u,int v,int cap,int cost) //25*m+j+30 區域 1-m //2000+i 蠟燭 1-n //t=2100; int main() { int n,m; scanf("%d%d",&n,&m); for(int j=1;j<=m;j++){ for(int i=1;i<=25;i++){ int cost=2*i-1; add(0,j*25+i,1,cost); add(j*25+i,25*m+j+30,1,0); } } for(int i=1;i<=n;i++){ int x,y;scanf("%d%d",&x,&y); add(25*m+x+30,2000+i,1,0); add(25*m+y+30,2000+i,1,0); add(2000+i,2100,1,0); } s=0;t=2100; printf("%d\n",mincost()); }