codeforces 1198E Rectangle Painting 2 最小点覆盖

匿名 (未验证) 提交于 2019-12-03 00:13:02

题目传送门

题意:

  你每次可以花费$ min (h,w)$的代价把一个$h*w$的矩形区域变白。求把所有黑格变白的最小代价。

思路:

  对于一列来说,如果我们要把这一列涂白,那必定会一涂到底,这样对结果只会有好处。行也是这样。

  明白了这个之后,这道题就变成了一道需要离散化的最小点覆盖问题,离散化时注意这个是网格,所以$x2,y2$都需要加1处理,然后跑一边网络流即可。

#pragma GCC optimize (2) #pragma G++ optimize (2) #pragma comment(linker, "/STACK:102400000,102400000") #include<bits/stdc++.h> #include<unordered_map> #define rep(i,a,b) for(int i=a;i<=b;++i) #define dep(i,b,a) for(int i=b;i>=a;--i) #define clr(a,b) memset(a,b,sizeof(a)) #define pb push_back #define pii pair<int,int > using namespace std; typedef long long ll; ll rd() {     ll x=0,f=1;char ch=getchar();     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}     return x*f; } const int inf=0x3f; const int maxn=8e5+10; const ll INFLL = 0x3f3f3f3f3f3f3f3f; const int INF = 0x3f3f3f3f;  struct Edge {     int to, flow, nxt;     Edge(){}     Edge(int to, int nxt, int flow):to(to),nxt(nxt), flow(flow){} }edge[maxn << 2];  int head[maxn], dep[maxn]; int S, T; int N, n, m, tot;  void Init(int n) {     N = n;     for (int i = 0; i <= N; ++i) head[i] = -1;     tot = 0; }  void addv(int u, int v, int w, int rw = 0) {     edge[tot] = Edge(v, head[u], w); head[u] = tot++;     edge[tot] = Edge(u, head[v], rw); head[v] = tot++; }  bool BFS() {     for (int i = 0; i <= N; ++i) dep[i] = -1;     queue<int>q;     q.push(S);     dep[S] = 1;     while (!q.empty())     {         int u = q.front();         q.pop();         for (int i = head[u]; ~i; i = edge[i].nxt)         {             if (edge[i].flow && dep[edge[i].to] == -1)             {                 dep[edge[i].to] = dep[u] + 1;                 q.push(edge[i].to);             }         }     }     return dep[T] < 0 ? 0 : 1; }  int DFS(int u, int f) {     if (u == T || f == 0) return f;     int w, used = 0;     for (int i = head[u]; ~i; i = edge[i].nxt)     {         if (edge[i].flow && dep[edge[i].to] == dep[u] + 1)         {             w = DFS(edge[i].to, min(f - used, edge[i].flow));             edge[i].flow -= w;             edge[i ^ 1].flow += w;             used += w;             if (used == f) return f;         }     }     if (!used) dep[u] = -1;     return used; }  int Dicnic() {     int ans = 0;     while (BFS())     {         ans += DFS(S, INF);     }     return ans; } vector<int >vx,vy; struct node{     int x1,y1,x2,y2; }a[60]; int main() {     while (~scanf("%d %d", &n, &m))     {         rep(i,1,m){             scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);             a[i].x2++,a[i].y2++;             vx.pb(a[i].x1),vx.pb(a[i].x2);             vy.pb(a[i].y1),vy.pb(a[i].y2);         }         sort(vx.begin(),vx.end());         vx.erase(unique(vx.begin(),vx.end()),vx.end());         sort(vy.begin(),vy.end());         vy.erase(unique(vy.begin(),vy.end()),vy.end());         int tx=vx.size(),ty=vy.size();         S = 0, T = tx * ty+1;         Init(T);         for(int i=0;i<tx-1;i++){             addv(S,i+1,vx[i+1]-vx[i]);         }         for(int i=0;i<ty-1;i++){             addv(tx+i+1,T,vy[i+1]-vy[i]);         }         for(int i=0;i<tx-1;i++){             for(int j=0;j<ty-1;j++){                 rep(k,1,m){                     if(a[k].x1<=vx[i]&&a[k].x2>=vx[i+1]&&a[k].y1<=vy[j]&&a[k].y2>=vy[j+1]){                         addv(i+1,tx+j+1,INF);                     }                 }             }         } //        printf("debug\n");         int ans = Dicnic();         printf("%d\n", ans);     } }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!