【最大费用流】【最优匹配】丘比特的烦恼 Vijos 1169
描述
隨著社會(huì)的不斷發(fā)展,人與人之間的感情越來(lái)越功利化。最近,愛(ài)神丘比特發(fā)現(xiàn),愛(ài)情也已不再是完全純潔的了。這使得丘比特很是苦惱,他越來(lái)越難找到合適的男女,并向他們射去丘比特之箭。于是丘比特千里迢迢遠(yuǎn)赴中國(guó),找到了掌管東方人愛(ài)情的神——月下老人,向他求教。
月下老人告訴丘比特,純潔的愛(ài)情并不是不存在,而是他沒(méi)有找到。在東方,人們講究的是緣分。月下老人只要做一男一女兩個(gè)泥人,在他們之間連上一條紅線,那么它們所代表的人就會(huì)相愛(ài)——無(wú)論他們身處何地。而丘比特的愛(ài)情之箭只能射中兩個(gè)距離相當(dāng)近的人,選擇的范圍自然就小了很多,不能找到真正的有緣人。
丘比特聽(tīng)了月下老人的解釋,茅塞頓開(kāi),回去之后用了人間的最新科技改造了自己的弓箭,使得丘比特之箭的射程大大增加。這樣,射中有緣人的機(jī)會(huì)也增加了不少。
情人節(jié)(Valentine's day)的午夜零時(shí),丘比特開(kāi)始了自己的工作。他選擇了一組數(shù)目相等的男女,感應(yīng)到他們互相之間的緣分大小,并依此射出了神箭,使他們產(chǎn)生愛(ài)意。他希望能選擇最好的方法,使被他選擇的每一個(gè)人被射中一次,且每一對(duì)被射中的人之間的緣分的和最大。
當(dāng)然,無(wú)論丘比特怎么改造自己的弓箭,總還是存在缺陷的。首先,弓箭的射程盡管增大了,但畢竟還是有限的,不能像月下老人那樣,做到“千里姻緣一線牽”。其次,無(wú)論怎么改造,箭的軌跡終歸只能是一條直線,也就是說(shuō),如果兩個(gè)人之間的連線段上有別人,那么莫不可向他們射出丘比特之箭,否則,按月下老人的話,就是“亂點(diǎn)鴛鴦譜”了。
作為一個(gè)凡人,你的任務(wù)是運(yùn)用先進(jìn)的計(jì)算機(jī)為丘比特找到最佳的方案。
格式
輸入格式
輸入第一行為正整數(shù)k,表示丘比特之箭的射程,第二行為正整數(shù)n(n<30),隨后有2n行,表示丘比特選中的人的信息,其中前n行為男子,后n行為女子。每個(gè)人的信息由兩部分組成:他的姓名和他的位置。姓名是長(zhǎng)度小于20且僅包含字母的字符串,忽略大小寫(xiě)的區(qū)別,位置是由一對(duì)整數(shù)表示的坐標(biāo),它們之間用空格分隔。格式為x y Name。輸入文件剩下的部分描述了這些人的緣分。每一行的格式為Name1 Name2 p。Name1和Name2為有緣人的姓名,p是他們之間的緣分值(p為小于等于255的正整數(shù))。以一個(gè)End作為文件結(jié)束標(biāo)志。每?jī)蓚€(gè)人之間的緣分至多只被描述一次。如果沒(méi)有被描述,則說(shuō)明他們緣分值為1。
輸出格式
輸出僅一個(gè)正整數(shù),表示每一對(duì)被射中的人之間的緣分的總和。這個(gè)和應(yīng)當(dāng)是最大的。
樣例1
樣例輸入1
2 3 0 0 Adam 1 1 Jack 0 2 George 1 0 Victoria 0 1 Susan 1 2 Cathy Adam Cathy 100 Susan George 20 George Cathy 40 Jack Susan 5 Cathy Jack 30 Victoria Jack 20 Adam Victoria 15 End樣例輸出1
65
不想吐槽了。。。。。
首先是題目描述,樣例明明是先讀入坐標(biāo)(x,y)在讀入名字,但是題目描述是先名字后坐標(biāo)。。。。糾結(jié)了好久。。。。
抱著試一試的心態(tài)才知道是先坐標(biāo)后名字
題目說(shuō)的沒(méi)有重邊,但是數(shù)據(jù)有!
得知數(shù)據(jù)有重邊后我又判斷,取最優(yōu)的那條邊,但是數(shù)據(jù)是取的最后出現(xiàn)的那條邊!
還有,幾何不好的孩子太苦逼了。。。。。。
下面是我們需要注意的幾點(diǎn)
1.弓箭的射程有限。?
2.箭的軌跡只能是一條直線,兩個(gè)人之間的連線段不能有別人。?
3.忽略大小寫(xiě)的區(qū)別。?
4.如果沒(méi)有被描述,則說(shuō)明他們緣分值為1,但并不一定有邊!(即在射程內(nèi))
6.重邊取最后一條
關(guān)鍵是第二點(diǎn)。判了好久啊。。。。。。。。。。。。。。。。。。。。。
做了一上午,都在判第二點(diǎn)。。。。。。
測(cè)評(píng)情況(Vijos):
C++ AC Code
/*http://blog.csdn.net/jiangzh7 By Jiangzh*/ #include<cstdio> #include<cctype> #include<cstring> #include<algorithm> #include<queue> #include<cmath> using namespace std; const int N=1000; const int inf=0x3f3f3f3f; #define sqr(_) ((_)*(_)) typedef long long LL; int K,n; struct node{char name[50];int x,y;}p[N]; int cap[N][N],cost[N][N]; int S,T; int dist[N],h[N],pre[N]; queue<int> q;void predoing(char *s)//全部轉(zhuǎn)化為小寫(xiě) {int len=strlen(s);for(int i=0;i<len;i++) s[i]=tolower(s[i]); }void read() {scanf("%d%d\n",&K,&n);for(int i=1;i<=n*2;i++){scanf("%d%d%s\n",&p[i].x,&p[i].y,p[i].name);predoing(p[i].name);} }int find(char *s)//找到對(duì)應(yīng)名字的序號(hào) {for(int i=1;i<=n*2;i++)if(!strcmp(s,p[i].name)) return i; }double dis(int x1,int y1,int x2,int y2)//距離 {return sqrt((double)sqr((LL)x1-x2)+(double)sqr((LL)y1-y2)); }bool check(int i,int j)//檢查能否連邊 {int x1=p[i].x,y1=p[i].y;int x2=p[j].x,y2=p[j].y;if(dis(x1,y1,x2,y2)>(double)K) return false;for(int i=1;i<=n+n;i++){if(p[i].x==x1&&p[i].y==y1) continue;if(p[i].x==x2&&p[i].y==y2) continue;int x0=p[i].x,y0=p[i].y;if((x0-x1)*(x0-x2)<=0 && (y0-y1)*(y0-y2)<=0)if((x0-x1)*(y2-y1)==(y0-y1)*(x2-x1))//p在boy和girl連線上return false;}return true; }void build_map()//建圖 {char b[50],g[50];for(int i=1;i<=n;i++)for(int j=n+1;j<=n+n;j++)if(dis(p[i].x,p[i].y,p[j].x,p[j].y)<=K)//必須在射程內(nèi){cap[i][j]=1;cost[i][j]=1;cost[j][i]=-1;}int x,y,w;while(1){memset(b,0,sizeof(b));memset(g,0,sizeof(g));scanf("%s",b);if(!strcmp(b,"End")) break;scanf("%s%d\n",g,&w);predoing(b);predoing(g);x=find(b);y=find(g);if(x>y) swap(x,y);//不一定是男在前,所以必要的時(shí)候交換一下位置if(check(x,y)){cost[x][y]=w;cost[y][x]=-w;}}S=0;T=n+n+1;//源點(diǎn)和匯點(diǎn)for(int i=1;i<=n;i++) {cap[S][i]=1;cost[S][i]=0;}for(int i=n+1;i<=n+n;i++) {cap[i][T]=1;cost[i][T]=0;} }bool spfa() {for(int i=S;i<=T;i++) dist[i]=-inf;dist[S]=0;q.push(S);while(!q.empty()){int x=q.front();q.pop();h[x]=false;for(int i=S;i<=T;i++)if(cap[x][i]>0 && dist[i]<dist[x]+cost[x][i]){pre[i]=x;dist[i]=dist[x]+cost[x][i];if(!h[i]){h[i]=true;q.push(i);}}}return dist[T]!=-inf; }void work() {build_map();int maxcost=0;while(spfa()){int res=inf;for(int i=T;i!=S;i=pre[i]){res=min(res,cap[pre[i]][i]);}for(int i=T;i!=S;i=pre[i]){cap[pre[i]][i]-=res;cap[i][pre[i]]+=res;}maxcost+=res*dist[T];}printf("%d\n",maxcost); }int main() {freopen("cupid.in","r",stdin);freopen("cupid.out","w",stdout);read();work();return 0; }總結(jié)
以上是生活随笔為你收集整理的【最大费用流】【最优匹配】丘比特的烦恼 Vijos 1169的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 中学教学参考杂志中学教学参考编辑部中学教
- 下一篇: ABCD 谁是小偷