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"; } };
相关文章推荐
- TCP三次握手及原理
- TC举例说明
- TC入门学习
- Tc 图形库graphics.h的函数库及用法(一)
- Tc 图形库graphics.h的函数库及用法
- Poj2638 网络流+最短路+二分答案
- BZOJ3275 Number (最小割)
- [笔记] 网络流-最大流 POJ-1273\HDU-4240
- 上下界网络流初探
- Edmonds-Karp 最大流 hdu 1532 Drained Ditches
- 网络流_poj1273
- POJ 1273 Drainage Ditches 最大流 dinic
- POJ1273-Drainage Ditches
- 【网络流】复杂的大门
- ACM/ICPC World Finals 2013 C Surely You Congest
- 网络流算法整理
- [BZOJ1797][AHOI2009][最大流][强连通分量]Mincut最小割
- [BZOJ2324][ZJOI2011][最小费用最大流]营救皮卡丘
- [BZOJ1834][ZJOI2010][最大流][最小费用最大流]网络扩容
- Topcoder SRM642 TaroCutting