http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5552

输入n,表示有n个数1到n。A先拿,B后拿,依次拿,每次可以拿任意一个数,同时会删去这个数的所有因子,最后谁没得拿了谁输。

解法:推了前几个,0,a输,别的a都能赢,证明没想,猜过去的。

网上一个人说的,也不是很清晰:“如果先取的在2-n中取必输,则先取1, 
否则则在2-n中取,同时会把1取走,必赢”

 #include<cstdio>
int main(){
int n;
while(~scanf("%d",&n)){
puts(n?"win":"fail");
}
return ;
}

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5555

n点m边无向图,每个点原来有ai,每个点最终需要bi,有边连就可以把任意个物品移动过去,移动一个物品的花费是1.

解法:最小费用最大流,比赛时建图如下

图中每个点拆成两个点u,u*,源点s连接每一个u,流量是ai,费用为0,ui 到 ui * 流量inf,费用为0, 输入的边在u之间建双向边,流量inf,费用1.

每一个 ui* 连汇点t,流量bi,费用0.

最后最大流要是sum of bi说明存在解,否则-1. 费用只会产生在u之间的边,最小费用就是这个题的答案。

 #include<cstdio>
#include<cstring>
#include<queue>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int inf=0x3f3f3f3f;
const int M=;
class MaxFlowMinCost { ///最小费用最大流 o(ME)
typedef int typef;///流量的类型
typedef int typec;///费用的类型
static const int ME=2e6+;///边的个数
static const int MV=2e2+;///点的个数
queue<int> q;
int cur[MV],pre[MV];
bool used[MV],sign[MV];
typef flow;
typec cost,dist[MV];
bool spfa(int s,int t) {
mt(used,);
mt(sign,);
mt(dist,);
used[s]=sign[s]=true;
while(!q.empty()) q.pop();
q.push(s);
while(!q.empty()) {
int u=q.front();
q.pop();
used[u]=false;
for(int i=g.head[u]; ~i; i=g.e[i].next) {
if(g.e[i].flow<) continue;
int v=g.e[i].v;
typec c=g.e[i].cost;
if(!sign[v]||dist[v]>dist[u]+c) {
dist[v]=dist[u]+c;
sign[v]=true; pre[v]=u;
cur[v]=i;
if(used[v]) continue;
used[v]=true;
q.push(v);
}
}
}
return sign[t];
} struct G {
struct E {
int v,next;
typef flow;
typec cost;
} e[ME];
int le,head[MV];
void init() {
le=;
mt(head,-);
} void add(int u,int v,typef flow,typec cost) {
e[le].v=v;
e[le].flow=flow;
e[le].cost=cost;
e[le].next=head[u];
head[u]=le++;
}
} g;
public:
void init() {
g.init();
} void add(int u,int v,typef flow,typec cost) {
g.add(u,v,flow,cost);
g.add(v,u,,-cost);
} void solve(int s,int t) {
flow=cost=;
while(spfa(s,t)) {
int temp=t;
typef now=inf;
while(temp!=s) {
now=min(now,g.e[cur[temp]].flow); temp=pre[temp];
}
flow+=now;
temp=t;
while(temp!=s) {
int id=cur[temp];
cost+=now*g.e[id].cost;
g.e[id].flow-=now;
g.e[id^].flow+=now;
temp=pre[temp];
}
}
} typef getflow() {
return flow;
} typec getcost() {
return cost;
}
}mfmc;
int a[M],b[M];
int main() {
int n,m,u,v;
while(~scanf("%d%d",&n,&m)) {
for(int i=; i<=n; i++) {
scanf("%d%d",&a[i],&b[i]);
}
mfmc.init();
int s=n+n+;
int t=s+;
int sum=;
for(int i=;i<=n;i++){
mfmc.add(s,i,a[i],);
mfmc.add(i+n,t,b[i],);
mfmc.add(i,i+n,inf,);
sum+=b[i];
}
while(m--) {
scanf("%d%d",&u,&v);
mfmc.add(u,v,inf,);
mfmc.add(v,u,inf,);
}
mfmc.solve(s,t);
int ans=-;
if(sum==mfmc.getflow()){
ans=mfmc.getcost();
}
printf("%d\n",ans);
}
return ;
}

后来看网上有个建图更好,不用拆点,想想也是,中间流量inf,费用0,那些就直接流过去了,我们可以在脑子把他跑掉,也就是我们只需要对n个点建图,对于输入的边,还是在uv之间建流量inf费用1的双向边,对于a》b的情况,从源点到u连a-b的流,费用0,对于a《b的情况,从u连到汇点t,流量b-a,。a==b的不用连了,这样建图的贪心的默认自己留给自己是最好的,想想也是挺对的。源点出来的流相当于每个点可提供的,流向汇点的相当于每个点的需求。

 #include<cstdio>
#include<cstring>
#include<queue>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int inf=0x3f3f3f3f;
const int M=;
class MaxFlowMinCost { ///最小费用最大流 o(ME)
typedef int typef;///流量的类型
typedef int typec;///费用的类型
static const int ME=6e2+;///边的个数
static const int MV=1e2+;///点的个数
queue<int> q;
int cur[MV],pre[MV];
bool used[MV],sign[MV];
typef flow;
typec cost,dist[MV];
bool spfa(int s,int t) {
mt(used,);
mt(sign,);
mt(dist,);
used[s]=sign[s]=true;
while(!q.empty()) q.pop();
q.push(s);
while(!q.empty()) {
int u=q.front();
q.pop();
used[u]=false;
for(int i=g.head[u]; ~i; i=g.e[i].next) {
if(g.e[i].flow<) continue;
int v=g.e[i].v;
typec c=g.e[i].cost;
if(!sign[v]||dist[v]>dist[u]+c) {
dist[v]=dist[u]+c;
sign[v]=true; pre[v]=u;
cur[v]=i;
if(used[v]) continue;
used[v]=true;
q.push(v);
}
}
}
return sign[t];
} struct G {
struct E {
int v,next;
typef flow;
typec cost;
} e[ME];
int le,head[MV];
void init() {
le=;
mt(head,-);
} void add(int u,int v,typef flow,typec cost) {
e[le].v=v;
e[le].flow=flow;
e[le].cost=cost;
e[le].next=head[u];
head[u]=le++;
}
} g;
public:
void init() {
g.init();
} void add(int u,int v,typef flow,typec cost) {
g.add(u,v,flow,cost);
g.add(v,u,,-cost);
} void solve(int s,int t) {
flow=cost=;
while(spfa(s,t)) {
int temp=t;
typef now=inf;
while(temp!=s) {
now=min(now,g.e[cur[temp]].flow); temp=pre[temp];
}
flow+=now;
temp=t;
while(temp!=s) {
int id=cur[temp];
cost+=now*g.e[id].cost;
g.e[id].flow-=now;
g.e[id^].flow+=now;
temp=pre[temp];
}
}
} typef getflow() {
return flow;
} typec getcost() {
return cost;
}
}mfmc;
int a[M],b[M];
int main() {
int n,m,u,v;
while(~scanf("%d%d",&n,&m)) {
for(int i=; i<=n; i++) {
scanf("%d%d",&a[i],&b[i]);
}
mfmc.init();
int s=;
int t=n+;
int sum=;
for(int i=;i<=n;i++){
if(a[i]>b[i]){
mfmc.add(s,i,a[i]-b[i],);
}
else if(a[i]<b[i]){
mfmc.add(i,t,b[i]-a[i],);
sum+=b[i]-a[i];
}
}
while(m--) {
scanf("%d%d",&u,&v);
mfmc.add(u,v,inf,);
mfmc.add(v,u,inf,);
}
mfmc.solve(s,t);
int ans=-;
if(sum==mfmc.getflow()){
ans=mfmc.getcost();
}
printf("%d\n",ans);
}
return ;
}

end

ZOJ Monthly, July 2015的更多相关文章

  1. 思维+multiset ZOJ Monthly, July 2015 - H Twelves Monkeys

    题目传送门 /* 题意:n个时刻点,m次时光穿梭,告诉的起点和终点,q次询问,每次询问t时刻t之前有多少时刻点是可以通过两种不同的路径到达 思维:对于当前p时间,从现在到未来穿越到过去的是有效的值,排 ...

  2. Twelves Monkeys (multiset解法 141 - ZOJ Monthly, July 2015 - H)

    Twelves Monkeys Time Limit: 5 Seconds      Memory Limit: 32768 KB James Cole is a convicted criminal ...

  3. ZOJ 3913 Bob wants to pour water ZOJ Monthly, October 2015 - H

    Bob wants to pour water Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge There i ...

  4. ZOJ 3911 Prime Query ZOJ Monthly, October 2015 - I

    Prime Query Time Limit: 1 Second      Memory Limit: 196608 KB You are given a simple task. Given a s ...

  5. ZOJ 3910 Market ZOJ Monthly, October 2015 - H

    Market Time Limit: 2 Seconds      Memory Limit: 65536 KB There's a fruit market in Byteland. The sal ...

  6. ZOJ 3908 Number Game ZOJ Monthly, October 2015 - F

    Number Game Time Limit: 2 Seconds      Memory Limit: 65536 KB The bored Bob is playing a number game ...

  7. ZOJ 3905 Cake ZOJ Monthly, October 2015 - C

    Cake Time Limit: 4 Seconds      Memory Limit: 65536 KB Alice and Bob like eating cake very much. One ...

  8. ZOJ 3903 Ant ZOJ Monthly, October 2015 - A

    Ant Time Limit: 1 Second      Memory Limit: 32768 KB There is an ant named Alice. Alice likes going ...

  9. matrix_2015_1 138 - ZOJ Monthly, January 2015

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3844 第一个,n个数,每次操作最大数和最小数都变成他们的差值,最后n个数相 ...

随机推荐

  1. ngx_http_upstream_module模块学习笔记

    ngx_http_upstream_module用于将多个服务器定义成服务器组,而由proxy_pass,fastcgi_pass等指令引用 (1)upstream name  {...} 定义一个后 ...

  2. BM串匹配算法

    串匹配算法最常用的情形是从一篇文档中查找指定文本.需要查找的文本叫做模式串,需要从中查找模式串的串暂且叫做查找串吧. BM算法好后缀规则 公式: 对于长度为m的模式串P,在i处失配时,模式串向前滑动的 ...

  3. 【php学习之路】php基础语法

    一.什么是php?       PHP即PHP: Hypertext Preprocessor(超文本处理器),是一种服务器端脚本语言,适用于创建web站点.开源免费 二.php能做什么?       ...

  4. .NET软件汉化小实例

    Author:KillerLegend Date:2014.6.18 From:http://www.cnblogs.com/killerlegend/p/3795577.html 好的,今天我们来汉 ...

  5. C++primer 阅读点滴记录(二)

      智能指针(smart point)       除了增加功能外,其行为像普通指针一样. 一般通过使用计数(use count)或引用计数(reference count)实现智能指针,防止出现指针 ...

  6. PuTTY 中文教程

    PuTTY 中文教程 更新记录 2006-11-29初步完成想写的这些东西 2007-06-11PuTTY 的最新版本到了0.6:修改了一下 SSH 隧道:添加了 SSH 反向隧道:添加了用 SSH ...

  7. 将python2.7+django1.10部署到SAE上

    首先我想说的是我为什么选择SAE呢?本人学生一枚,没钱.然后sae好像又有免费的一定限额,所以我就选了它. 期间曲折颇多,实在不是三言两语所能道情的.各种百度,谷歌,最后所幸成功了,幸哉! 主要参考了 ...

  8. Python 2.7的安装(64位win10)

    Python 2.7.12 下载地址:https://www.python.org/downloads/release/python-2712/ 安装路径D:\Program Files\Python ...

  9. 关于activity_main.xml与fragment_main.xml

    第一种解决办法 新版安装SDK文件一开始有两个XML文件,activity_main.xml和fragment_main.xml,不习惯的可以这样处理:1.删除fragment_main.xml整个文 ...

  10. .net控件事件中的Sender

    private void button2_Click(object sender, RoutedEventArgs e) { } 最近看WPF内容,回顾下.net大家天天都在用,却不是十分关注的一个对 ...