P1500 丘比特的烦恼
題目描述
隨著社會的不斷發展,人與人之間的感情越來越功利化。最近,愛神丘比特發現,愛情也已不再是完全純潔的了。這使得丘比特很是苦惱,他越來越難找到合適的男女,并向他們射去丘比特之箭。于是丘比特千里迢迢遠赴中國,找到了掌管東方人愛情的神——月下老人,向他求教。
月下老人告訴丘比特,純潔的愛情并不是不存在,而是他沒有找到。在東方,人們講究的是緣分。月下老人只要做一男一女兩個泥人,在他們之間連上一條紅線,那么它們所代表的人就會相愛——無論他們身處何地。而丘比特的愛情之箭只能射中兩個距離相當近的人,選擇的范圍自然就小了很多,不能找到真正的有緣人。
丘比特聽了月下老人的解釋,茅塞頓開,回去之后用了人間的最新科技改造了自己的弓箭,使得丘比特之箭的射程大大增加。這樣,射中有緣人的機會也增加了不少。
情人節(Valentine’s day)的午夜零時,丘比特開始了自己的工作。他選擇了一組數目相等的男女,感應到他們互相之間的緣分大小,并依此射出了神箭,使他們產生愛意。他希望能選擇最好的方法,使被他選擇的每一個人被射中一次,且每一對被射中的人之間的緣分的和最大。
當然,無論丘比特怎么改造自己的弓箭,總還是存在缺陷的。首先,弓箭的射程盡管增大了,但畢竟還是有限的,不能像月下老人那樣,做到“千里姻緣一線牽”。其次,無論怎么改造,箭的軌跡終歸只能是一條直線,也就是說,如果兩個人之間的連線段上有別人,那么莫不可向他們射出丘比特之箭,否則,按月下老人的話,就是“亂點鴛鴦譜”了。
作為一個凡人,你的任務是運用先進的計算機為丘比特找到最佳的方案。
輸入格式
輸入第一行為正整數k,表示丘比特之箭的射程,第二行為正整數n(n<30),隨后有2n行,表示丘比特選中的人的信息,其中前n行為男子,后n行為女子。每個人的信息由兩部分組成:他的姓名和他的位置。姓名是長度小于20且僅包含字母的字符串,忽略大小寫的區別,位置是由一對整數表示的坐標,它們之間用空格分隔。格式為x y Name。輸入文件剩下的部分描述了這些人的緣分。每一行的格式為Name1 Name2 p。Name1和Name2為有緣人的姓名,p是他們之間的緣分值(p為小于等于255的正整數)。以一個End作為文件結束標志。每兩個人之間的緣分至多只被描述一次。如果沒有被描述,則說明他們緣分值為1。
輸出格式
輸出僅一個正整數,表示每一對被射中的人之間的緣分的總和。這個和應當是最大的。
題解:
比較明顯的最大費用最大流,就是要注意的地方比較多
1.名字不區分大小寫,需要全部轉換成小寫或者大寫
2.洛谷明確標注了每兩個人緣分最多被描述一次,而BZOJ會有這種數據,直接覆蓋直接的緣分值即可
3.一定不能判斷前三個字母是End就退出,會有些數據的人名前三個字母就是End…
4.兩點間是否有一個點滿足三點一線隨便找個板子就好了
5.沒有被描述的兩個人緣分值為1
注意到這些建圖完了直接跑一遍EK就OK了
AC代碼:
#pragma GCC optimize(2) #include<bits/stdc++.h> #include<ext/rope> using namespace std; using namespace __gnu_cxx; #define LL long long const int MAXN = 2000+50; const int MAXM = 2e6+50; const int MOD = 1e9+7; const int INF = 0x3f3f3f3f; int n,d,s,t,tot=1,maxflow,res,head[MAXN],to[MAXM],w[MAXM],nxt[MAXM],co[MAXM]; int dis[MAXN],vis[MAXN],pre[MAXN],flow[MAXN],g[50][50]; struct node{ int x,y; string ss; }a[MAXN]; inline void deal(string &s){for(int i=0;i<(int)s.length();i++) s[i]=tolower(s[i]); } inline double distance(int x,int y,int xx,int yy){return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy)); } inline bool check(int x,int y){if(distance(a[x].x,a[x].y,a[y].x,a[y].y)>d) return false;for(int i=1;i<=2*n;i++){if(i==x || i==y) continue;double d1=distance(a[x].x,a[x].y,a[i].x,a[i].y);double d2=distance(a[y].x,a[y].y,a[i].x,a[i].y);double d3=distance(a[x].x,a[x].y,a[y].x,a[y].y);if(d1+d2-d3<1e-9) return false;}return true; } inline void ade(int u,int v,int ww,int cost){to[++tot]=v; w[tot]=ww; co[tot]=cost; nxt[tot]=head[u]; head[u]=tot; } inline void add(int u,int v,int w,int cost){ ade(u,v,w,cost); ade(v,u,0,-cost); } inline int spfa(){for(int i=0;i<=t;i++) dis[i]=-INF;queue<int> que; que.push(s); dis[s]=0; vis[s]=1; flow[s]=INF;while(!que.empty()){int u=que.front(); que.pop(); vis[u]=0;for(int i=head[u];i;i=nxt[i]){if(w[i] && dis[to[i]]<dis[u]+co[i]){dis[to[i]]=dis[u]+co[i]; pre[to[i]]=i;flow[to[i]]=min(flow[u],w[i]);if(!vis[to[i]]) vis[to[i]]=1,que.push(to[i]);}}}return dis[t]!=-INF; } inline void EK(){while(spfa()){res+=flow[t]*dis[t]; int x=t;while(x!=s){int i=pre[x];w[i]-=flow[t]; w[i^1]+=flow[t]; x=to[i^1];}} } signed main(){ #ifndef ONLINE_JUDGEfreopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin); #endif // ONLINE_JUDGEscanf("%d%d",&d,&n); s=0,t=2*n+1;for(int i=1;i<=2*n;i++) cin>>a[i].x>>a[i].y>>a[i].ss,deal(a[i].ss);string s1,s2; int k;while(cin>>s1){if(s1=="End") break;cin>>s2>>k; int p1=0,p2=0;deal(s1); deal(s2);for(int i=1;i<=2*n;i++) if(a[i].ss==s1) p1=i;for(int i=1;i<=2*n;i++) if(a[i].ss==s2) p2=i;if(p1>p2) swap(p1,p2); g[p1][p2]=k;}for(int i=1;i<=n;i++) add(s,i,1,0),add(i+n,t,1,0);for(int i=1;i<=n;i++){for(int j=n+1;j<=2*n;j++){if(check(i,j)){if(g[i][j]) add(i,j,1,g[i][j]);else add(i,j,1,1);}}}EK();printf("%d\n",res);return 0; }總結
以上是生活随笔為你收集整理的P1500 丘比特的烦恼的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 语句摘抄——第22周
- 下一篇: erlang与rabbitmq下载(Wi