1001: [BeiJing2006]狼抓兔子
Time Limit: 15 Sec Memory Limit: 162 MBDescription
Input
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
HINT
都说是什么平面图转对偶图,但是,这难道不是赤裸裸的最小割嘛?
别忘了建边的时候,正反都要有流量,因为都需要。
#include<bits/stdc++.h> using namespace std; #define inf 2147483647 #define ll long long inline int read(){ int x=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar(); } return x; } int n,m,s,t; int ip; struct E{ int to;ll cap; }e[8000100]; vector<int> l[1000100]; int lv[1000100]; int b[1000100]; bool bfs(){ memset(lv,-1,sizeof(lv)); lv[s]=0; queue<int>q; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=0;i<l[u].size();i++){ int t=l[u][i]; int v=e[t].to; if(lv[v]==-1&&e[t].cap>0){ lv[v]=lv[u]+1; q.push(v); } } } return lv[t]!=-1; } int dfs(int now,int mf){ if(now==t||mf==0)return mf; ll tf=mf; for(;b[now]<l[now].size();b[now]++){ int t=l[now][b[now]]; int v=e[t].to; if(lv[v]==lv[now]+1&&e[t].cap!=0){ ll f=dfs(v,min(tf,e[t].cap)); tf-=f; e[t].cap-=f; e[t^1].cap+=f; if(tf==0)return mf; } } lv[now]=-1; return mf-tf; } int dinic(){ ll ret=0; while(bfs()){ memset(b,0,sizeof(b)); ret+=dfs(s,inf); } return ret; } void insert(int u,int v,int c){ e[ip].to=v; e[ip].cap=c; l[u].push_back(ip++); } int main(){ n=read(),m=read(); s=1;t=n*m; int x; for(int i=1;i<=n;i++) for(int j=1;j<m;j++) { scanf("%d",&x); insert(m*(i-1)+j,m*(i-1)+j+1,x); insert(m*(i-1)+j+1,m*(i-1)+j,x); } for(int i=1;i<n;i++) for(int j=1;j<=m;j++) { scanf("%d",&x); insert(m*(i-1)+j,m*(i)+j,x); insert(m*(i)+j,m*(i-1)+j,x); } for(int i=1;i<n;i++) for(int j=1;j<m;j++) { scanf("%d",&x); insert(m*(i-1)+j,m*(i)+j+1,x); insert(m*(i)+j+1,m*(i-1)+j,x); } cout<<dinic(); return 0; }
1002: [FJOI2007]轮状病毒
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5577 Solved: 3031
[Submit][Status][Discuss]
Description
轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子
和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道。如下图所示
N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不
同的3轮状病毒,如下图所示
Input
第一行有1个正整数n
Output
计算出的不同的n轮状病毒数输出
1007: [HNOI2008]水平可见直线
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 7590 Solved: 2902
[Submit][Status][Discuss]
Description
在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为
可见的,否则Li为被覆盖的.
例如,对于直线:
L1:y=x; L2:y=-x; L3:y=0
则L1和L2是可见的,L3是被覆盖的.
给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.
Input
第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi
Output
从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格
Sample Input
-1 0
1 0
0 0
Sample Output
#include<bits/stdc++.h> using namespace std; #define eps 1e-8 int n; struct T{ double a,b; int num; }l[50001],st[50001]; bool ans[50001];int top; double crossx(T x1,T x2) {return (x2.b-x1.b)/(x1.a-x2.a);} void insert(T a) { while(top) { if(fabs(st[top].a-a.a)<eps)top--; else if(top>1&&crossx(a,st[top-1])<=crossx(st[top],st[top-1])) top--; else break; } st[++top]=a; } void work() { for(int i=1;i<=n;i++)insert(l[i]); for(int i=1;i<=top;i++)ans[st[i].num]=1; for(int i=1;i<=n;i++) if(ans[i])printf("%d ",i); } bool cmp(T w,T e){ if(fabs(w.a-e.a)<eps)return w.b<e.b; else return w.a<e.a; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lf%lf",&l[i].a,&l[i].b); l[i].num=i; } sort(l+1,l+n+1,cmp); work(); return 0; }
小插曲 刚才Never Penta kill 问我一道题
1658: [Usaco2006 Mar]Water Slides 滑水
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 231 Solved: 152
[Submit][Status][Discuss]
Description
It's a hot summer day, and Farmer John is letting Betsy go to the water park where she intends to ride every single slide. The water park has N (1 <= N <= 10,000) platforms (numbered 1..N) from which to enter the M (1 <= M <= 10,000) water slides. Each water slide starts at the top of some platform and ends at the bottom of some platform (possibly the same one). Some platforms might have more than one slide; some might not have any. The park is very thin, so the platforms lie along a straight line, each platform at a position Xi (0 <= Xi <= 100,000) meters from one end of the park. One walks from one platform to the next via a sidewalk parallel to the line of platforms.The platforms of the water park are weakly connected; that is, the park cannot be divided into two sets of platforms with no slides running between the two sets. Both the entrance and exit to the park are at platform 1, so Betsy will start and end there. In order to spend more time on the slides, Betsy wants to walk as little as possible. Find the minimum distance Betsy must travel along the ground in order to try every slide in the park exactly once without repeating.
炎热的夏日里,约翰带贝茜去水上乐园滑水.滑水是在一条笔直的人工河里进行的,沿河设有N(1≤N≤10000)个中转站,并开通了M(1≤M≤10000)条滑水路线.路线的起点和终点总在某个中转站上,起点和终点可能相同.有些中转站可能是许多条路线的起点或终点,而有些站则可能没有在任何路线里被用上.贝茜希望能把所有的路线都滑一遍. 所有中转站排成一条直线,每个中转站位于离河的源头Xi(0≤Xi≤100000)米处.沿着河边的人行道,贝茜可以从任意位置走到任意一个中转站. 中转站与滑水路线的布局满足下述的性质:任意两个中转站之间都有滑水路线直接成间接相连.水上乐园的入口与出口都在1号中转站旁,也就是说,贝茜的滑水路线的起点和终点都是1号中转站.
为了更好地享受滑水的快乐,贝茜希望自己花在走路上的时间越少越好.请你帮她计算一下,如果按她的计划,把所有的路线都不重复地滑一遍,那她至少要走多少路.
Input
* Line 1: Two integers, N and M.
* Lines 2..N+1: Line i+1 contains one integer, Xi, the position of platform i. * Lines N+2..M+N+1: Line i+N+1 contains two integers, Si and Di, respectively the start and end platforms of a slide.
第1行:两个整数N和M,用空格隔开.
第2到N+1行:第i+l行包括一个整数Xi,表示i号中转站距河源头的距离.
第N+2到M+N+1行:第i+N+1行包括两个整数Si和Di,分别表示了一条滑水路线的起点和终点.
Output
* Line 1: One integer, the minimum number of meters Betsy must walk.
输出一个整数,即贝茜要走的路程长度至少为多少米
Sample Input
5
3
1
7
10
1 2
1 2
2 3
3 1
4 5
1 5
4 1
Sample Output
HINT
贝茜先按1~2~3~1~2路径滑水.然后走2米,回到1.她再滑行到5,走到4,滑行
到5,走到4,最后滑回1(数字代表中转站号).
这样,她所走的总路程为8米.
#include <bits/stdc++.h> using namespace std; int n,m; int pos[10010],s[10010],d[10010],du[10010]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",pos+i); int x,y; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); du[x]++;du[y]--; } int a=0,b=0; for(int i=1;i<=n;i++){ for(;du[i]>0;du[i]--)s[++a]=pos[i]; for(;du[i]<0;du[i]++)d[++b]=pos[i]; } sort(s+1,s+a+1); sort(d+1,d+b+1); int ans=0; for(int i=1;i<=a;i++){ ans+=abs(s[i]-d[i]); } cout<<ans; return 0; }
1008: [HNOI2008]越狱
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 9933 Solved: 4278
[Submit][Status][Discuss]
Description
监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果
相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱
Input
输入两个整数M,N.1<=M<=10^8,1<=N<=10^12
Output
可能越狱的状态数,模100003取余
Sample Input
Sample Output
HINT
6种状态为(000)(001)(011)(100)(110)(111)
#include <bits/stdc++.h> using namespace std; #define ll long long #define mod 100003 ll power(ll a,ll b){ if(b==0)return 1; else if(b&1)return power(a*a%mod,b>>1)*a%mod; else return power(a*a%mod,b>>1); } int main() { ll n,m; cin>>m>>n; printf("%d",(power(m,n)-(m*power(m-1,n-1))%mod+mod)%mod); }
1012: [JSOI2008]最大数maxnumber
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 10829 Solved: 4739
[Submit][Status][Discuss]
Description
现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。
Input
第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。
Output
对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。
Sample Input
A 96
Q 1
A 97
Q 1
Q 2
Sample Output
93
96
HINT
数据如下http://pan.baidu.com/s/1i4JxCH3
啊啊啊啊啊,就这个破玩意,我当时写了一上午的线段树。。。
后来崩溃了,改成单调队列。1A。。。理论上单调队列可以卡成n方啊,,,为什么可以A啊
#include<bits/stdc++.h> using namespace std; int a[200001],m[2000001]; int main(){ int n,d,l=0,x,ans=0; char f[4]; scanf("%d%d",&n,&d); while(n--){ scanf("%s%d",f,&x); if(f[0]=='A'){ a[++l]=(x+ans)%d; for(int i=l;i>=1;i--){ if(m[i]<a[l])m[i]=a[l]; else break; } } else { ans=m[l-x+1]; printf("%d\n",ans); } } }
就这个效果。。。
1015: [JSOI2008]星球大战starwar
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 6504 Solved: 3018
[Submit][Status][Discuss]
Description
很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。某一天,凭着一个偶然的
机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直
接或间接地连接。 但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划
地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。现在,反抗军首
领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每
一次打击之后反抗军占据的星球的连通快的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则
这两个星球在同一个连通块中)。
Input
输入文件第一行包含两个整数,N (1 < = N < = 2M) 和M (1 < = M < = 200,000),分别表示星球的
数目和以太隧道的数目。星球用 0 ~ N-1的整数编号。接下来的M行,每行包括两个整数X, Y,其中(0 < = X <>
Y 表示星球x和星球y之间有“以太”隧道,可以直接通讯。接下来的一行为一个整数k,表示将遭受攻击的星球的
数目。接下来的k行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这k个数互不相同,且都在0到n-1的范
围内。
Output
第一行是开始时星球的连通块个数。接下来的K行,每行一个整数,表示经过该次打击后现存星球
的连通块个数。
Sample Input
0 1
1 6
6 5
5 0
0 6
1 2
2 3
3 4
4 5
7 1
7 2
7 6
3 6
5
1
6
3
5
7
Sample Output
1
1
2
3
3
1022: [SHOI2008]小约翰的游戏John
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2820 Solved: 1794
[Submit][Status][Discuss]
Description
小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取
的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取,我们规定取到最后一
粒石子的人算输。小约翰相当固执,他坚持认为先取的人有很大的优势,所以他总是先取石子,而他的哥哥就聪明
多了,他从来没有在游戏中犯过错误。小约翰一怒之前请你来做他的参谋。自然,你应该先写一个程序,预测一下
谁将获得游戏的胜利。
Input
本题的输入由多组数据组成第一行包括一个整数T,表示输入总共有T组数据(T≤500)。每组数据的第一行包
括一个整数N(N≤50),表示共有N堆石子,接下来有N个不超过5000的整数,分别表示每堆石子的数目。
Output
每组数据的输出占一行,每行输出一个单词。如果约翰能赢得比赛,则输出“John”,否则输出“Brother”
,请注意单词的大小写。
Sample Input
3
3 5 1
1
1
Sample Output
Brother
#include<bits/stdc++.h> using namespace std; #define inf 2147483647 #define ll long long inline int read(){ int x=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar(); } return x; } int main(){ int t=read(); while(t--){ int n=read(); int x=0; int p; int f=0; for(int i=1;i<=n;i++){ p=read(); x^=p; if(p!=1)f=1; } if((x!=0&&f==1)||(x==0&&f==0))printf("John\n"); else printf("Brother\n"); } return 0; }
1024: [SCOI2009]生日快乐
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2841 Solved: 2074
[Submit][Status][Discuss]
Description
windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕。现在包括windy
,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋糕。windy主刀,每一切只能平行于一块蛋糕
的一边(任意一边),并且必须把这块蛋糕切成两块。这样,要切成 N 块蛋糕,windy必须切 N-1 次。为了使得
每块蛋糕看起来漂亮,我们要求 N块蛋糕的长边与短边的比值的最大值最小。你能帮助windy求出这个比值么?
Input
包含三个整数,X Y N。1 <= X,Y <= 10000 ; 1 <= N <= 10
Output
包含一个浮点数,保留6位小数。
Sample Input
Sample Output
#include <bits/stdc++.h> using namespace std; #define ll long long #define inf 1e9 double dfs(double x,double y,int cnt){ if(cnt==1)return max(x/y,y/x); double maxn=inf; for(int i=1;i<=cnt>>1;i++){ maxn=min(maxn,max(dfs(x/cnt*i,y,i),dfs(x/cnt*(cnt-i),y,cnt-i))); maxn=min(maxn,max(dfs(x,y/cnt*i,i),dfs(x,y/cnt*(cnt-i),cnt-i))); } return maxn; } int main() { double x,y;int n; cin>>x>>y>>n; printf("%.6lf",dfs(x,y,n)); return 0; }