您的位置:首页 > 理论基础 > 计算机网络

TC SRM 680(div 2) 1000pts

2016-01-29 02:17 471 查看

题意:

It’s a well-known fact that Limak, as every bear, owns a set of numbers. You know some information about the set:

The elements of the set are distinct positive integers.

The number of elements in the set is n. The number n is divisible by 3.

All elements are between 1 and b, inclusive: bears don’t know numbers greater than b.

For each r in {0,1,2}, the set contains exactly n/3 elements that give remainder r when divided by 3. (That is, there are n/3 elements divisible by 3, n/3 elements of the form 3k+1, and n/3 elements of the form 3k+2.)

Limak smiles mysteriously and gives you q hints about his set. The hints are numbered 0 through q-1. For each valid i, the hint number i is the following sentence: “If you only look at elements that are between 1 and upTo[i], inclusive, you will find exactly quantity[i] such elements in my set.”

In a moment Limak will tell you the actual puzzle, but something doesn’t seem right… That smile was very strange. You start to think about a possible reason. Maybe Limak cheated you? Or is he a fair grizzly bear?

You are given the ints n and b. You are also given the vector s upTo and quantity. Return “fair” (quotes for clarity) if there exists at least one set that has all the required properties and matches all the given hints. Otherwise, return “unfair”.

思路:

网络流搞!

没时间写了,赛后过题,泪奔!

把 1−b 每个数看成一个点,设 s0, s1, s2 分别为模3后的余数为0,1,2的点集,源点 S 向s0, s1, s2连边,流量均为 n3;

s0, s1, s2 分别向对应点集连边,流量为1;

对于所有的询问,排完序我们可以得到每个区间[L,R] 内有Vi个点出现在最终满足条件点集中,把每个区间看作一个点 Ci,由区间内的点向 Ci 连边,流量为1,由 Ci 向 汇点 T 连边,流量为 Vi ;

最后跑一遍最大流,看是否满流即可!

啥都别说了!



代码:

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <string>
#define PB push_back
#define FT first
#define SD second
#define MP make_pair
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int>  P;
vector<P> V;
bool cmp(const P a, const P b)
{
if(a.FT == b.FT) return a.SD < b.SD;
return a.FT < b.FT;
}
const int N = 1100,M = 5+1e5,MOD=7+1e9;
struct Node
{
int from,to,next;
int cap;
}edge[M];
int tol;

int dep
;//dep为点的层次
int head
;

void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)//第一条变下标必须为偶数
{
edge[tol].from=u;
edge[tol].to=v;
edge[tol].cap=w;//注意正向边流量值
edge[tol].next=head[u];
head[u]=tol++;

edge[tol].from=v;
edge[tol].to=u;
edge[tol].cap=0;//注意反向边的流量值
edge[tol].next=head[v];
head[v]=tol++;
}

int BFS(int start,int end)
{
int que
;
int front,rear;
front=rear=0;
memset(dep,-1,sizeof(dep));
que[rear++]=start;
dep[start]=0;
while(front!=rear)
{
int u=que[front++];
if(front==N)front=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>0&&dep[v]==-1)
{
dep[v]=dep[u]+1;
que[rear++]=v;
if(rear>=N)rear=0;
if(v==end)return 1;
}
}
}
return 0;
}
int dinic(int start,int end)
{
int res=0;
int top;
int stack
;//stack为栈,存储当前增广路
int cur
;//存储当前点的后继
while(BFS(start,end))
{
memcpy(cur,head,sizeof(head));
int u=start;
top=0;
while(1)
{
if(u==end)
{
int min=INF;
int loc;
for(int i=0;i<top;i++)
if(min>edge[stack[i]].cap)
{
min=edge[stack[i]].cap;
loc=i;
}
for(int i=0;i<top;i++)
{
edge[stack[i]].cap-=min;
edge[stack[i]^1].cap+=min;
}
res+=min;
top=loc;
u=edge[stack[top]].from;
}
for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
break;
if(cur[u]!=-1)
{
stack[top++]=cur[u];
u=edge[cur[u]].to;
}
else
{
if(top==0)break;
dep[u]=-1;
u=edge[stack[--top]].from;
}
}
}
return res;
}
class BearFair2 {
public:
string isFair(int n, int b, vector <int> upTo, vector <int> quantity) {
int Q = upTo.size();
V.clear();
V.PB(MP(b, n)), V.PB(MP(0, 0));
for(int i = 0;i < Q;i ++) {
V.PB(MP(upTo[i], quantity[i]));
}
sort(V.begin(), V.end(), cmp);
bool ok = 1;
for(int i = 1;i < V.size();i ++) {
int x = V[i].FT - V[i-1].FT;
if(V[i].SD < V[i-1].SD || V[i].SD - V[i-1].SD > x) {
ok = 0;
break;
}
}
if(!ok) return "unfair";
init();
int S0 = b + Q + 3, S1 = S0 + 1, S2 = S0 + 2, S = S2 + 1, T = S + 1;
addedge(S, S0, n/3), addedge(S, S1, n/3), addedge(S, S2, n/3);
for(int i = 1;i <= b;i ++) {
if(i % 3 == 0) addedge(S0, i, 1);
else if(i % 3 == 1) addedge(S1, i, 1);
else addedge(S2, i, 1);
}
for(int i = 1;i < V.size();i ++) {
for(int j = V[i-1].FT + 1;j <= V[i].FT;j ++) {
addedge(j, b + i, 1);
}
addedge(b + i, T, V[i].SD - V[i-1].SD);
}
return dinic(S, T) == n ? "fair" : "unfair";
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  TC 网络流