recently I’ve done a lot network flow problem and this is one of them
first of all , there is only 10 potential player who can be the king so we can iter them form
let’s talk about how to build the network,once we build the network with k kings we can check the maximum flow ,if it is equal to the number of all edges,so the network or the graph we build is correct
- link all matches i with the source capacity is 1
- link all the player with sink point ,capacity is 1
- for all match that involve player i,j ,
- the score of the smaller one is the king , we link match i with the smaller one , because the king of them must beat all the player whose score is higher than itself,and for that the result is established. Capacity is 1
- and the rest match m related to i,j we link both i,j,to match m also the cap i 1
so this question become a max_flow problem!
#include <cstdio>
#include <cstring>
#include <stack>
#include <cstring>
#include <cctype>
#define ll long long
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=150;//点数的最大值
const int MAXM=20500;//边数的最大值
struct Node
{
int from,to,next;
int cap;
} edge[MAXM];
int tol;
int dep[MAXN];//dep为点的层次
int head[MAXN];
int n;
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[MAXN];
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==MAXN)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>=MAXN)rear=0;
if(v==end)return 1;
}
}
}
return 0;
}
int dinic(int start,int end)
{
int res=0;
int top;
int stack[MAXN];//stack为栈,存储当前增广路
int cur[MAXN];//存储当前点的后继
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;
}
int score[20000],match[20000][2000],tot;
void read()
{
char s[1000];
gets(s);
n=0;
for(int i=0;s[i];i++)
{
int temp=0;
if( isdigit(s[i]) )
{
while(s[i] && isdigit(s[i]) )
{
temp=temp*10+s[i]-'0';
++i;
}
--i;
score[++n]=temp;
}
}
}
bool build_and_check(int c)
{
init();
//tot = n*(n-1)/2;
int s = 0,t = n+1;
for(int i = 1; i<=n; i++)
{
addedge(i,t,score[i]);
}
for(int i = n+2; i<tot; i++)
{
addedge(s,i,1);
}
//int match= 1;
for(int i =1; i<=n; i++)
{
for(int j = i+1; j<=n; j++)
{
if(score[i] > score[j] && j >= n-c+1)
{
addedge(match[i][j],j,1);
}
else if(score[i] < score[j] && i >= n-c+1)
{
addedge(match[i][j],i,1);
}
else
{
addedge(match[i][j],i,1);
addedge(match[i][j],j,1);
}
}
}
int ans = dinic(s,t);
//printf("%d\n",ans);
return ans == (n*(n-1)/2);
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
int ca = 0;
//char str[100];
scanf("%d%*c",&ca);
while(ca--)
{
n = 0;
//cout<<str<<endl;
read();
//cout<<n<<endl;
tot = n+2;
for(int i = 1; i<=n; i++)
{
for(int j =i+1; j<=n; j++)
{
match[i][j] = match[j][i] = tot++;
}
}
for(int i = n; i>=0; i--)
{
if(build_and_check(i))
{
printf("%d",i);
break;
}
}
printf("\n");
}
return 0;
}
and thanks to kuangbin for his good dinic algorithm implementation