10.11考试反思

10.11 

Contest2141 - 2019年10月多校联训B层测试10

T1  劳作

 

 http://www.accoders.com/problem.php?cid=2141&pid=0  题目传送门 

  T1 搜索 (for循环裸题) 每次输入的时候,记一下行和列出现的*次数以及总共的次数,然后枚举横行纵列就可以了,遇到一个可以的位置直接输出 return 就可以了

 

#include <bits/stdc++.h>
#define ll long long
#define res register 
#define MAXN 100050
#define int ll 
using namespace std;
int n,m,cnt,h[MAXN],stx,sty,sum,q[MAXN];
char a;
bool ju[3050][3050];
ll read()
{
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-48;ch=getchar();}
    return s*w;
}
#undef int
int main()
{
    #define int ll
    n=read(),m=read();
    for(res int i=1;i<=n;i++)
    for(res int j=1;j<=m;j++){
        cin>>a;
        if(a=='*') ju[i][j]=1,h[i]++,q[j]++,sum++;
    }
    for(res int i=1;i<=n;i++)
    for(res int j=1;j<=m;j++){
        if(h[i]+q[j]-ju[i][j]==sum) 
        {
            cout<<"YES"<<endl;
            cout<<i<<" "<<j<<endl;
            return 0;
        }
    }
    cout<<"NO"<<endl;
    return 0;
}
View Code

 

T2  浇水

http://www.accoders.com/problem.php?cid=2141&pid=1

T2是真的搜索 我们需要dfs2次,第一次求出来所有的湖泊数目,以及起点的横纵坐标存到结构体里,然后贪心,sort一下,填前k小的,然后输出就可以了

 

#include <bits/stdc++.h>
#define MAXN 100050
#define res register 
#define db double
#define int ll
#define standard 1e-5
#define ll long long 
using namespace std;
int n,m,dx[4]={0,1,0,-1},dy[4]={-1,0,1,0},ans,b[MAXN],k,tot,cnt,sum;
char wa[1050][1050];
bool vis[1050][1050],ju;
struct Node{
    int ans,x,y;
    friend inline bool operator<(Node a,Node b){
        return a.ans>b.ans;
    }
}a[MAXN];
inline void dfs(int x,int y){
    if(x==1||y==1||x==n||y==m) ju=0;
    vis[x][y]=1,tot++;
    for(res int i=0;i<4;i++){
        int xx=x+dx[i],yy=y+dy[i];
        if(xx>=1&&yy>=1&&xx<=n&&yy<=m&&!vis[xx][yy]&&wa[xx][yy]=='.') dfs(xx,yy);
    }
}
inline void dfs2(int x,int y){
    wa[x][y]='*';
    for(int i=0;i<4;i++){
        int xx=x+dx[i],yy=y+dy[i];
        if(wa[xx][yy]=='.')
        dfs2(xx,yy);
    }
}
ll read()
{
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-48;ch=getchar();}
    return s*w;
}
signed main()
{
    n=read(),m=read(),k=read();
    for(res int i=1;i<=n;i++)
    for(res int j=1;j<=m;j++) cin>>wa[i][j];
    for(res int i=1;i<=n;i++)
    for(res int j=1;j<=m;j++){
        if(!vis[i][j]&&wa[i][j]=='.'){
            ju=1;tot=0;
            dfs(i,j);if(ju){
                a[++cnt].x=i,a[cnt].y=j;a[cnt].ans=tot;
            }
        }
    }
    sort(a+1,a+1+cnt);
    for(res int i=cnt;i>k;i--)
    sum+=a[i].ans,dfs2(a[i].x,a[i].y);
    cout<<sum<<endl;
    for(res int i=1;i<=n;i++){
        for(res int j=1;j<=m;j++)
        cout<<wa[i][j];
        cout<<endl;
    }
    return 0;
}
View Code

 

T3  买菜

http://www.accoders.com/problem.php?cid=2141&pid=2

一道比较有难度的题,首先对于题意,我们需要求你所选择的蔬菜所构成的这个图的最大团,也就是求补图的最大独立集,我们建立补图的时候是个二分图,除了1,1连边之外就是奇数偶数连边,所以构成了二分图,考虑求二分图的最大匹配,匈牙利,但是显然这道题有点权,匈牙利算法不可解,我们换一种方法,很显然,dinic就可以解决了。我们考虑二分查找答案,用Dinic作check即可

  1 #include <bits/stdc++.h>
  2 #define MAXN 120
  3 #define res register 
  4 #define inf 0x3f3f3f3f
  5 #define db double
  6 #define int ll
  7 #define standard 1e-5
  8 #define ll long long 
  9 using namespace std;
 10 struct Edge{
 11     int to,nxt,dis;
 12 }g[30050];
 13 struct Node{
 14     int p,c,l;
 15 }a[MAXN];
 16 bool np[300050]={1,1};
 17 int n,m,k,head[MAXN],ss,tt,top,dis[MAXN];
 18 inline void add(int u,int v,int dis){
 19     g[++top].to=v,g[top].nxt=head[u];
 20     g[top].dis=dis;head[u]=top;
 21     g[++top].to=u;g[top].nxt=head[v];
 22     g[top].dis=0;head[v]=top;
 23 }
 24 bool vis[MAXN];
 25 inline bool bfs(){
 26     memset(dis,0,sizeof(dis));
 27     memset(vis,0,sizeof(vis));
 28     queue<int>q;
 29     vis[ss]=1;q.push(ss);
 30     while(!q.empty()){
 31         int u=q.front();q.pop();
 32         for(int i=head[u];~i;i=g[i].nxt){
 33             int v=g[i].to;
 34             if(g[i].dis&&!vis[v]){
 35                 q.push(v);vis[v]=1;
 36                 dis[v]=dis[u]+1;
 37             }
 38         }
 39     }
 40     return vis[tt];
 41 }
 42 inline int dfs(int u,int fa){
 43     if(u==tt) return fa;
 44     int qwq=0;
 45     for(int i=head[u];fa&&~i;i=g[i].nxt){
 46         int v=g[i].to;
 47         if(g[i].dis&&dis[v]==dis[u]+1){
 48             int flow=dfs(v,min(g[i].dis,fa));
 49             g[i].dis-=flow;
 50             g[i^1].dis+=flow;
 51             fa-=flow;
 52             qwq+=flow;
 53         }
 54     }
 55     return qwq;
 56 }
 57 inline int dinic(){
 58     int qwq=0;while(bfs()) qwq+=dfs(ss,inf);
 59     return qwq;
 60 }
 61 inline bool check(int x){
 62     top=-1;memset(head,-1,sizeof(head));
 63     int m=-1,w=-1;
 64     for(res int i=1;i<=n;i++)
 65     if(a[i].l<=x) if(a[i].c==1&&a[i].p>m) m=a[i].p,w=i;
 66     int ans=0;
 67     for(res int i=1;i<=n;i++)
 68     if(a[i].l<=x){
 69         if(a[i].c==1&&i!=w) continue;
 70         ans+=a[i].p;
 71         if(a[i].c&1){
 72             add(ss,i,a[i].p);
 73             for(res int j=1;j<=n;j++)
 74             if(a[j].l<=x&&(~a[j].c&1)&&!np[a[i].c+a[j].c])
 75             add(i,j,inf);
 76         }
 77         else add(i,tt,a[i].p);
 78     }
 79     ans-=dinic();
 80     return ans<k;
 81 }
 82 inline int erfen(int l,int r){
 83     if(l==r) return l;
 84     int mid=l+r>>1;if(!check(mid)) erfen(l,mid);
 85     else erfen(mid+1,r);
 86 }
 87 ll read()
 88 {
 89     int s=0,w=1;char ch=getchar();
 90     while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
 91     while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-48;ch=getchar();}
 92     return s*w;
 93 }
 94 inline void Init(){
 95     for(int i=2;i<=200000;++i)if(!np[i])
 96     for(int j=i*2;j<=200000;j+=i) np[j]=1;
 97 }
 98 signed main()
 99 {
100     n=read(),k=read();Init();ss=n+1,tt=n+2;
101     for(res int i=1;i<=n;i++) a[i].p=read(),a[i].c=read(),a[i].l=read();
102     cout<<erfen(1,n+1)<<endl;
103     return 0;
104 }
View Code

 

 

总结 这道题难点在于如何快速的把这个问题转化到网络流及二分图上,难点在于建立模型

posted @ 2019-11-12 14:37  落筱  阅读(170)  评论(0编辑  收藏  举报