zoukankan      html  css  js  c++  java
  • 洛谷 P2765 魔术球问题 (最小路径覆盖 or 贪心)

    题目

    (戳我)[https://www.luogu.com.cn/problem/P2765]

    思路

    两种思路,第一种贪心很明显了,我们直接从第一个开始放球,可以放就放,不能放就新开一个。第二种的话建图,首先我们应该发现这个东西的特点,一个柱子可以放多个球,有多个柱子,但是每个柱子的球是不可能一样的,这和图论里面二分图的最小路径覆盖很像,因此我们选择拆点建图,然后对这个图不断加点,当我的顶点数-最大匹配大于最小路径的时候,就是答案了。贪心大法好!!!

    代码实现

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=getchar();
        } while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        } return x*f;
    }
    const int maxn=1e4+10;
    const int M=5e5+10;
    struct edge {
        int u,v,flow,next;
    }e[M];
    int head[maxn],cnt=-1;
    
    inline void add (int u,int v,int flow) {
        e[++cnt]=(edge) {u,v,flow,head[u]};
        head[u]=cnt;
    }
    inline void add_edge (int u,int v,int flow) {
        add (u,v,flow);
        add (v,u,0);
    }
    
    int dis[maxn],cur[maxn];
    int ss,s,t,n,m,x,y,ans;
    int bfs () {
        MT (dis,0);
        queue<int > q;
        q.push (ss);
        dis[ss]=1;
        while (q.size ()) {
            int x=q.front (); q.pop ();
            for (int i=head[x];i!=-1;i=e[i].next) {
                if (dis[e[i].v]==0&&e[i].flow) {
                    dis[e[i].v]=dis[x]+1;
                    q.push (e[i].v);
                }
            }
        }
        return dis[t];
    }
    
    int dfs (int now,int nowflow) {
        if (now==t) return nowflow;
        for (int &i=cur[now];~i;i=e[i].next) {
            if (dis[e[i].v]==dis[now]+1&&e[i].flow) {
                int canflow=dfs (e[i].v,min (nowflow,e[i].flow));
                if (canflow>0) {
                    e[i].flow-=canflow;
                    e[i^1].flow+=canflow;
                    return canflow;
                }
            }
        }
        return 0;
    }
    
    inline int Dinic () {
    	int ans=0;
        while (bfs ()) {
           memcpy (cur,head,sizeof (head));
           while (int val=dfs(ss,inf)) ans+=val;
        }
    	return ans;
    }
    
    int pre[maxn],vis[maxn];
    
    int main () {
    	MT (head,-1);
        scanf ("%d",&n);
    	t=10000;
    	while (1) {
           ans++,s++;
    	   rev (i,1,s) if (sqrt (i+s)==(int) (sqrt (i+s))) {
    		   add_edge (i,s+5000,1);
    	   }
    	   add_edge (0,s,1);
    	   add_edge (s+5000,t,1);
    	   int st=Dinic ();
    	   ans-=st;
    	   if (ans>n) break;
    	}
    	printf ("%d
    ",s-1);
    
    	rev (i,1,s) {
    		int k=head[i];
    		while (k) {
    			if (!e[k].flow) {
    				pre[i]=e[k].v-5000;
    				break;
    			}
    			k=e[k].next;
    		}
    	}
    	rev (i,1,s) {
    		if (vis[i]) continue;
    		int p=i;
    		while (p!=-5000) {
    			vis[p]=1;
    			printf ("%d ",p);
    			p=pre[p];
    		}
    		cout<<endl;
    
    	}
    	return 0;
    }
    
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    const int mod=1e9+7;
    typedef long long ll;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=getchar();
        } while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        } return x*f;
    }
    
    const int maxn=60;
    VI v[maxn];
    set <int> s;
    int n;
    
    void prework () {
        rep (i,1,maxn) {
            s.insert (i*i);
        }
    }
    
    int main () {
        cin>>n;
        int cnt=0,ans=1;
        prework ();
        while (true) {
            rep (i,1,cnt) {
                int x=v[i].back ()+ans;
                if (s.count (x)) {
                 v[i].pb (ans);
                 ans++;
                 i=0;
                 continue;
                }
            }
            if (cnt<n) v[++cnt].pb (ans++);
            else break;
        }
        cout<<ans-1<<endl;
        rep (i,1,n) {
            for (auto it:v[i]) {
                printf ("%d ",it);
            }
            cout<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    视频基础知识 720P、1080i、1080P
    PS/ES/TS区别
    服务端时间与COOKIE问题
    H.264名词
    一组视频音频编辑软件的介绍
    浅述WinForm多线程编程与Control.Invoke的应用
    [原创]补丁工具V1.6.3
    .net序列化与反序列化错误,可能是Local Settings\Temp不存在引起
    通过IViewObject接口,取浏览器的图象,实现SNAP
    C#实现一个用于开机启动其他程序的Windows服务
  • 原文地址:https://www.cnblogs.com/hhlya/p/13549861.html
Copyright © 2011-2022 走看看