zoukankan      html  css  js  c++  java
  • ACM2017Tsukuba:H

    第一问求最多,不需要区分数学作业和信息作业,直接模拟就行了
    第二问考虑每天只能产生1的贡献,每天拆成两个点,限制每天只能有1的贡献,剩下的源点连数学作业,信息作业连汇点,再将数学作业和信息作业连能连的天数。
    跑一边最大流就行了
    代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    void read(int &x) {
    	char ch; bool ok;
    	for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    	for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
    }
    queue<int>q;
    #define rg register
    const int maxn=401,maxm=5e5+1,inf=1e9;
    int cur[maxm],dis[maxm],n,m,s,t,ans1,ans2,cnt=1,mx,pre[maxm],nxt[maxm],h[maxm],v[maxm];bool vis[maxn];
    struct oo{int l,r;}a[maxn];
    void add(int x,int y,int z)
    {
    	pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,v[cnt]=z;
    	pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt,v[cnt]=0;
    }
    bool bfs()
    {
    	memset(dis,0,sizeof dis);dis[s]=1;q.push(s);
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();
    		for(rg int i=h[x];i;i=nxt[i])if(v[i]&&!dis[pre[i]])dis[pre[i]]=dis[x]+1,q.push(pre[i]);
    	}
    	return dis[t];
    }
    int dfs(int x,int flow)
    {
    	if(x==t||!flow)return flow;
    	int f=flow;
    	for(rg int &i=cur[x];i;i=nxt[i])
    		if(v[i]&&dis[pre[i]]>dis[x])
    		{
    			int y=dfs(pre[i],min(v[i],f));
    			f-=y,v[i]-=y,v[i^1]+=y;
    			if(!f)return flow;
    		}
    	if(f==flow)dis[x]=-1;
    	return flow-f;
    }
    int main()
    {
    	read(n),read(m);
    	for(rg int i=1;i<=n;i++)read(a[i].l),read(a[i].r),mx=max(mx,a[i].r);
    	for(rg int i=1;i<=mx;i++)
    	{
    		int mn=1e9,mnn=1e9;
    		for(rg int j=1;j<=n;j++)
    			if(!vis[j]&&i>=a[j].l&&i<=a[j].r&&(mn>a[j].r||(mn==a[j].r&&mnn>j)))mn=a[j].r,mnn=j;
    		if(mnn<1e9)vis[mnn]=1,ans1++;
    	}
    	s=0,t=n*2+mx*2+1;
    	for(rg int i=1;i<=m;i++)
    	{
    		add(s,i,1);
    		for(rg int j=a[i].l;j<=a[i].r;j++)add(i,n+j*2-1,1);
    	}
    	for(rg int j=1;j<=mx;j++)add(n+j*2-1,n+j*2,1);
    	for(rg int i=m+1;i<=n;i++)
    	{
    		add(i,t,1);
    		for(rg int j=a[i].l;j<=a[i].r;j++)add(n+j*2,i,1);
    	}
    	for(;bfs();ans2+=dfs(s,inf))memcpy(cur,h,sizeof h);
    	printf("%d
    %d
    ",ans1,ans2);
    }
    
  • 相关阅读:
    LeetCode Path Sum
    实训篇-Html-表单练习
    实训篇-Html-frameset框架集
    实训篇-Html-超链接练习
    实训篇-Html-列表练习
    实训篇-Html-表格练习2
    实训篇-Html-表格练习1
    实训篇-Html-超链接a标签使用
    实训篇-Html-多媒体标签
    实训篇-Html-标题,段落,字体
  • 原文地址:https://www.cnblogs.com/lcxer/p/10319811.html
Copyright © 2011-2022 走看看