二分图的最小点权覆盖。

非常感谢巨巨@islands_的解答,还帮我画了一个图。

题目保证给出的边构成的图是一个二分图。

如果没有第三种类型的$frog$,那么问题就很简单了。即选择哪些点,覆盖住所有的边,并且要求选择的点的权值之和最小。可以转换成网络流来解决。

现在有第三种类型的$frog$,可以把这种$frog$拆成两个点,两点之间连边,然后其余和他有矛盾的点,分别向两个点中的一个点连边。画画图可以发现拆点之后的新图也是二分图。对这个图跑一次二分图的最小点权覆盖,如果拆点的边两端有一个点被选择,说明这个$frog$实际上是不选择的,如果拆点的边两端有两个点被选择,说明这个$frog$实际上被选择了,那么只要在结果上减去第三种类型的$frog$的权值和就可以了。

#include<bits/stdc++.h>
using namespace std; int n,m;
int w[],p[],dis[];
vector<int>g[]; const int maxn = + ;
const int INF = 0x7FFFFFFF;
struct Edge
{
int from, to, cap, flow;
Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){}
};
vector<Edge>edges;
vector<int>G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
int s, t; void init()
{
for (int i = ; i < maxn; i++) G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, int cap)
{
edges.push_back(Edge(from, to, cap, ));
edges.push_back(Edge(to, from, , ));
int w = edges.size();
G[from].push_back(w - );
G[to].push_back(w - );
}
bool BFS()
{
memset(vis, , sizeof(vis));
queue<int>Q;
Q.push(s);
d[s] = ;
vis[s] = ;
while (!Q.empty())
{
int x = Q.front();
Q.pop();
for (int i = ; i<G[x].size(); i++)
{
Edge e = edges[G[x][i]];
if (!vis[e.to] && e.cap>e.flow)
{
vis[e.to] = ;
d[e.to] = d[x] + ;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x, int a)
{
if (x == t || a == )
return a;
int flow = , f;
for (int &i = cur[x]; i<G[x].size(); i++)
{
Edge e = edges[G[x][i]];
if (d[x]+ == d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>)
{
edges[G[x][i]].flow+=f;
edges[G[x][i] ^ ].flow-=f;
flow+=f;
a-=f;
if(a==) break;
}
}
if(!flow) d[x] = -;
return flow;
}
int dinic(int s, int t)
{
int flow = ;
while (BFS())
{
memset(cur, , sizeof(cur));
flow += DFS(s, INF);
}
return flow;
} void B(int x)
{
queue<int>Q; Q.push(x); dis[x]=; while(!Q.empty())
{
x = Q.front(); Q.pop();
for(int i=;i<g[x].size();i++)
{
int to = g[x][i];
if(dis[to]!=-) continue;
dis[to] = dis[x]^;
Q.push(to);
}
}
} void ADD(int a,int b)
{
g[a].push_back(b);
g[b].push_back(a);
} int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=;i<=*n;i++) g[i].clear(); for(int i=;i<=n;i++) scanf("%d",&w[i]);
for(int i=;i<=n;i++)
{
scanf("%d",&p[i]);
if(p[i]==) ADD(i,i+n);
} for(int i=;i<=m;i++)
{
int A,B; scanf("%d%d",&A,&B);
if(p[A]+p[B]==) continue; if(p[A]==||p[A]==)
{
if(p[B]==||p[B]==) ADD(A,B);
else
{
if(p[A]==) ADD(A,B);
else ADD(A,B+n);
}
} else if(p[A]==)
{
if(p[B]==||p[B]==)
{
if(p[B]==) ADD(A,B);
else ADD(A+n,B);
}
else if(p[B]==)
{
ADD(A,B);
ADD(A+n,B+n);
}
}
} memset(dis,-,sizeof dis);
for(int i=;i<=*n;i++)
{
if(dis[i]!=-) continue;
B(i);
} init(); s=,t=*n+; for(int i=;i<=*n;i++)
{
if(dis[i]==) continue;
for(int j=;j<g[i].size();j++) AddEdge(i,g[i][j],INF);
} for(int i=;i<=*n;i++)
{
int V;
if(i<=n) V = w[i]; else V=w[i-n];
if(dis[i]==) AddEdge(s,i,V);
else AddEdge(i,t,V);
} int ans = dinic(s,t);
for(int i=;i<=n;i++) if(p[i]==) ans=ans-w[i]; printf("%d\n",ans); }
return ;
}

SCU 4442 Party的更多相关文章

  1. SCU 4442 party 二分图最大点权独立集

    每个青蛙喝黑茶或者红茶或者都可以喝 M个矛盾关系 有矛盾的不能喝同种茶 但你可以花费Wi使得这个青蛙消除所有矛盾 把矛盾当作边 青蛙当作点 如果这两个青蛙只喝不同的一种茶就不建边 题目中保证了不存在奇 ...

  2. scu oj 4442 Party(2015年四川省acm程序设计竞赛)

    Party n frogs are invited to a tea party. Frogs are conveniently numbered by 1,2,-,n. The tea party ...

  3. ACM:SCU 4437 Carries - 水题

    SCU 4437  Carries Time Limit:0MS     Memory Limit:0KB     64bit IO Format:%lld & %llu  Practice  ...

  4. ACM: SCU 4438 Censor - KMP

     SCU 4438 Censor Time Limit:0MS     Memory Limit:0KB     64bit IO Format:%lld & %llu  Practice D ...

  5. ACM: SCU 4440 Rectangle - 暴力

     SCU 4440 Rectangle Time Limit:0MS     Memory Limit:0KB     64bit IO Format:%lld & %llu  Practic ...

  6. SCU 4424(求子集排列数)

    A - A Time Limit:0MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice ...

  7. SCU 2941 I NEED A OFFER!(01背包变形)

    I NEED A OFFER!     64bit IO Format: %lld & %llu Submit Status Description Description Speakless ...

  8. HDU 4442 Physical Examination

    Physical Examination Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64 ...

  9. SCU 4440 分类: ACM 2015-06-20 23:58 16人阅读 评论(0) 收藏

    SCU - 4440 Rectangle Time Limit: Unknown   Memory Limit: Unknown   64bit IO Format: %lld & %llu ...

随机推荐

  1. Mac下安装SVN插件javaHL not available的解决方法

    在Mac下安装Eclipse插件svnEclipse插件后,每次打开Eclipse都会弹出如下弹出框: 提示你本机缺少JavaHL Library. 选择Eclipse→偏好设置(preference ...

  2. Arrays.asList方法遇到的问题

    在使用Arrays.asList(T...a)方法时,遇到了 java.lang.UnsupportedOperationException  异常. 后来发现,该方法返回的类型是Arrays$Arr ...

  3. gulpfile.js文档

    gulp watch 实现监听不仅需要package.json文档,还需要gulpfile.js文档.否则无法实现. 1.gulp的安装 1.1 首先必须先安装node.js.这个可以参考之前的博客& ...

  4. Debian sudo自动补全

    解决 debian sudo TAB 键不能自动补全命令的原因 一般情况,命令行输入 sudo apt-get ins 按 tab ,它后面会自动补全为 install 如果右面写了包的名的一部分,按 ...

  5. Codeforces 221 A. Little Elephant and Function

    A. Little Elephant and Function time limit per test 2 seconds memory limit per test 256 megabytes in ...

  6. js中不能做变量名的字符

    JavaScript中不能作为变量名的关键字和保留字总结: 1.js中的关键字: break case catch continue default delete do else finally fo ...

  7. matlab核函数与滑窗

    在处理图像时,为了提取特征,经常用各种核函数和图像进行卷积,其实就是通过一个矩阵以滑窗的形式与原图像进行点乘求和,可以看作对一个像素和附近像素进行了加权平均. 比如经常用3x3的近似高斯卷积核 0 1 ...

  8. 【leetcode 简单】第九题 移除元素

    给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...

  9. LOW逼三人组(一)----冒泡算法

    排序 1.冒泡排序 冒泡算法 import random # 随机模块 def bubble_sort(li): ###################################冒泡排序#### ...

  10. UNIX环境高级编程学习笔记(十)为何 fork 函数会有两个不同的返回值【转】

    转自:http://blog.csdn.net/fool_duck/article/details/46917377 以下是基于 linux 0.11 内核的说明. 在init/main.c第138行 ...