Andrew Stankevich Contest 10 I Trade 有下届网络流

用Dinic跑一遍,关键是建图


#include<bits/stdc++.h>
#define MEM(a,x) memset(a,x,sizeof(a));
#define MEMINF(a) memset(a,0x3f,sizeof(a));
using namespace std;
typedef long long LL;
const int MAXN=1e6+10;
const int INF=0x3f3f3f3f;
const int MOD=1000000007;
struct Edge{
  int to,nex,cap,id;
}edge[MAXN];

int top;
int head[MAXN],gap[MAXN],point[MAXN];
void Addedges(int u,int v,int cap,int id) {
  edge[top].id=id;
  edge[top].cap=cap;
  edge[top].to=v;
  edge[top].nex=head[u];
  head[u]=top++;
}

void Addedge(int u,int v,int cap,int id) {
  Addedges(u,v,cap,id);
  Addedges(v,u,0,id);
}


int  bfs(int s,int t) {
  MEM(gap,-1);
  queue<int>q;
  gap[s]=0;
  q.push(s);
  while (!q.empty()) {
    int u=q.front();
    q.pop();
    for (int i=head[u]; ~i; i=edge[i].nex) {
      int v=edge[i].to,cap=edge[i].cap;
      if (cap>0&&gap[v]<0) {
        gap[v]=gap[u]+1;
        q.push(v);
      }
    }
  }
  return gap[t];
}

int dfs(int s,int t,int flow) {
  int f;
  if (s==t) return flow;
  for (int i=head[s]; ~i; i=edge[i].nex) {
    if (edge[i].cap>0&&gap[s]<gap[edge[i].to])
    if ((f=dfs(edge[i].to,t,min(flow,edge[i].cap)))>0) {
      edge[i].cap-=f;
      edge[i^1].cap+=f;
      return f;
    }
  }
  return 0;
}
int Dinic (int s,int t,int cntV) {
  int flow=0;
  int f;
  while(bfs(s,t)>=0) {
    while((f=dfs(s,t,INF))>0)
      flow+=f;
  }
  return flow;
}
int main() {
  freopen("trade.in","r",stdin);
  freopen("trade.out","w",stdout);
  int m,n,p;
  cin>>m>>n>>p;
  MEM(head,-1);
  top=0;
  int s=m+n,t=m+n+1;
  int cntS=m+n+2,cntT=m+n+3;
  int cntV=m+n+4;
  for (int i=1; i<=p; ++i) {
    int u,v;
    scanf("%d %d",&u,&v);
    Addedge(u-1,m+v-1,1,i);
  }
  for (int i=0; i<m; ++i) {
    Addedge(s,i,INF,0);
    Addedge(cntS,i,2,0);
  }
  for(int i=0; i<n; ++i) {
    Addedge(i+m,t,INF,0);
    Addedge(i+m,cntT,2,0);
  }
  Addedge(s,cntT,2*m,0);
  Addedge(cntS,t,2*n,0);
  int tflow=n*2+m*2;
  int tmp=Dinic(cntS,cntT,cntV);
  Addedge(t,s,INF,0);
  tmp+=Dinic(cntS,cntT,cntV);
  if (tmp!=tflow) {
    puts("-1");
    return 0;
  }
  vector<int>ans;
  for (int i=0; i<m; ++i) {
    for (int u=head[i]; ~u; u=edge[u].nex) {
      if (edge[u].cap==0&&(edge[u].to>=m&&edge[u].to<n+m))
          ans.push_back(edge[u].id);
    }
  }
  printf("%d\n",(int) ans.size());
  sort(ans.begin(),ans.end());
  printf("%d ",ans[0]);
  for (int i=1; i<ans.size(); ++i) 
    printf("%d%c",ans[i]," \n"[i==ans.size()-1]);
}

       


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值