您的位置:首页 > 其它

TC-SRM617div1-500

2014-05-10 11:45 302 查看
虽然说每次做完TC 官方都会给出很厚道的题解,但是毕竟每个人从中学到的东西不尽相同。因此还是打算写一个这样的题解来做一些不明觉厉的总结以上。

这道题的题意是给出两个数组choice1[]和choice2[],表示对于每个i你可以选择choice1[i]=1 ,choice2[i]=2 或者 choice1[i]=2 ,choice2[i]=1。分别表示给choice1[i]一号奖励并给choice2[i]二号奖励,或者给choice1[i]二号奖励并且给choice2[i]一号奖励。目的是使Σ|number1[p]-number2[p]|最小。其中number1[p]表示的是p所获得的的一号奖励的个数,number2[p]表示的是p所获得的二号奖励的个数。

首先要注意到的是这个题目的决策是具有传递性的。即对于choice1[i],choice2[i],choice1[i+1],choice2[i+1] 如果有 (choice1[i] 或者 choice2[i])==(choice1[i+1] 或者 choice2[i+1])那么其他两个决策是会造成相互影响的。那么我们把这个传递性表示为a-->b  b-->c得出a-->c 那么根据这个传递性 我们为了控制变量就会考虑使得中间变量无关,或者等价无关是否可以做到。然后就参考题解中的神构图了,如果choice1[i]=1
,choice2[i]=2 则 使得这条边的方向从choice1[i]指向choice2[i]。而number1[choice1[i]]即为其choice1[i]的入度,number2[choice1[i]] 为其出度,对于图上的某一段点开始若该端点的oude[nox]-inde[nox]>=2则对于任意oude[des]<inde[des]为终点的链,将其经过的所有边反向,所得到的的结果必定比原先的结果要优。

因为对于起点而言经过反向 得到的权值是 abs( oude[nox]-1-(inde[nox]+1))

对于中间节点得到的权值是 abs(oude[i]+1-inde[i]-1)

对于终点而言得到的权值是 abs(oude[i]+1-(inde[i]-1))

易得必定解更优。



上图可以转化为



于是本题可解。

即为先按照给出的choice1与choice2构图,找到oude[nox]-inde[nox]>=2或者inde[nox]-oude[nox]>=2的点,之后找到出入度大小关系与之相反的终点,使该路径上所有边反向,知道不存在oude[nox]-inde[nox]>=2或者inde[nox]-oude[nox]>=2的点

最关键的是找出传递性和构造中间等效无关的状态,然后应用出入度进行构图求解

#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include<cstring>

using namespace std;

class PieOrDolphin {
public:
vector <int> Distribute(vector <int> choice1, vector <int> choice2) {
int inde[60],oude[60];
memset(inde,0,sizeof(inde));
memset(oude,0,sizeof(oude));
int m=choice1.size();
vector<int>res(m,1);
int i,s,t,tmp,u,v;
for (i=0;i<m;i++){
oude[choice1[i]]++;
inde[choice2[i]]++;
}
while (1){
s=-1;
for (i=0;i<50;i++)
if (abs(inde[i]-oude[i])>=2){
s=i;
break;
}
if (s==-1)
break;
if (inde[s]>oude[s]){
for (i=0;i<m;i++)
if (res[i]==1)
res[i]=2;
else
res[i]=1;
for (i=0;i<50;i++){
tmp=inde[i];
inde[i]=oude[i];
oude[i]=tmp;
}
}
int que[1005],lq,rq;
int fah[60],nofa[60];
lq=rq=0;que[0]=s;
memset(fah,-1,sizeof(fah));
memset(nofa,-1,sizeof(nofa));
t=-1;
while (lq<=rq){
int x=que[lq];
if (inde[x]>oude[x]){
t=x;
break;
}
for (i=0;i<m;i++){
if (res[i]==1){
u=choice1[i];
v=choice2[i];
}
else{
u=choice2[i];
v=choice1[i];
}
if (u==x && v!=s && fah[v]==-1){
fah[v]=x;
nofa[v]=i;
que[++rq]=v;
}
}
lq++;
}
if (t==-1)
break;
int lop=t;
while (fah[lop]!=-1){
if (res[nofa[lop]]==1)
res[nofa[lop]]=2;
else
res[nofa[lop]]=1;
u=lop;v=fah[lop];
inde[u]--;
oude[u]++;
inde[v]++;
oude[v]--;
lop=fah[lop];
}
}
return (res);
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: