FOJ 11月月赛题解

抽空在vjudge上做了这套题。剩下FZU 2208数论题不会。

FZU 2205

这是个想法题,每次可以在上一次基础上加上边数/2的新边。

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 #include <string>
 5 #include <string.h>
 6 #include <stdio.h>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <set>
11 #include <cmath>
12 #include <ctime>
13 #include <cassert>
14 #include <sstream>
15 using namespace std;
16
17 const int N=2001;
18
19 int f[N];
20 int main () {
21     f[1]=0;
22     for (int i=2;i<=1000;i++) {
23         f[i]=f[i-1]+i/2;
24     }
25     int T;
26     cin>>T;
27     while (T--) {
28         int n;
29         cin>>n;
30         cout<<f[n]<<endl;
31     }
32     return 0;
33 }

FZU 2206

乍看不知道什么东西,直接在机器上跑几个数字可以试出来结论。

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 #include <string>
 5 #include <string.h>
 6 #include <stdio.h>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <set>
11 #include <cmath>
12 #include <ctime>
13 #include <cassert>
14 #include <sstream>
15 using namespace std;
16
17 const int N=501;
18 const int INF=0x3f3f3f3f;
19
20
21 int main () {
22     //freopen("out.txt","r",stdin);
23     int T;
24     scanf("%d",&T);
25     for (int cas=1;cas<=T;cas++) {
26         long long n;
27         scanf("%I64d",&n);
28         if (n<20150001LL) cout<<n+2014<<endl;
29         else cout<<20152014<<endl;
30     }
31     return 0;
32 }

FZU 2207

会用倍增算LCA的话,这题也肯定会做。

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <string>
  5 #include <string.h>
  6 #include <stdio.h>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <set>
 11 #include <cmath>
 12 #include <ctime>
 13 #include <cassert>
 14 #include <sstream>
 15 using namespace std;
 16
 17 const int N=2001;
 18
 19 vector<int>e[N];
 20 int fa[N][13];
 21 int dep[N];
 22 void dfs(int u,int f,int d) {
 23     dep[u]=d;
 24     for (int i=0;i<e[u].size();i++) {
 25         int v=e[u][i];
 26         if (v==f) continue;
 27         dfs(v,u,d+1);
 28         fa[v][0]=u;
 29     }
 30 }
 31
 32 void calc(int n) {
 33     for (int j=1;j<=12;j++) {
 34         for (int i=1;i<=n;i++) {
 35             fa[i][j]=fa[fa[i][j-1]][j-1];
 36         }
 37     }
 38 }
 39
 40 int kthA(int u,int k) {
 41     for (int i=12;i>=0;i--) {
 42         if (k>=(1<<i)){
 43             k-=(1<<i);
 44             u=fa[u][i];
 45         }
 46     }
 47     return u;
 48 }
 49
 50 int lca(int u,int v) {
 51     if (dep[u]<dep[v]) swap(u,v);
 52     int d=dep[u]-dep[v];
 53     u=kthA(u,d);
 54     if (u==v) return u;
 55     for (int i=12;i>=0;i--) {
 56         if (fa[u][i]==fa[v][i])
 57             continue;
 58         u=fa[u][i];
 59         v=fa[v][i];
 60     }
 61     return fa[u][0];
 62 }
 63 int main () {
 64     int T;
 65     scanf("%d",&T);
 66     while (T--) {
 67         int n,m;
 68         scanf("%d %d",&n,&m);
 69         for (int i=0;i<=n;i++)
 70             e[i].clear();
 71         for (int i=1;i<n;i++) {
 72             int u,v;
 73             scanf("%d %d",&u,&v);
 74             e[u].push_back(v);
 75             e[v].push_back(u);
 76         }
 77         dfs(1,-1,1);
 78         calc(n);
 79         static int cas=1;
 80         printf("Case #%d:\n",cas++);
 81         while (m--) {
 82             int u,v,k;
 83             scanf("%d %d %d",&u,&v,&k);
 84             int ans=lca(u,v);
 85             if (k==1) {
 86                 printf("%d\n",u);
 87                 continue;
 88             }
 89             else if (k==dep[u]-dep[ans]+dep[v]-dep[ans]+1) {
 90                 printf("%d\n",v);
 91                 continue;
 92             }
 93             if (dep[u]-dep[ans]+1>=k) {
 94                 int ret=kthA(u,k-1);
 95                 printf("%d\n",ret);
 96             }
 97             else {
 98                 int to=dep[u]-dep[ans]+dep[v]-dep[ans]+1-k;
 99                 int ret=kthA(v,to);
100                 printf("%d\n",ret);
101             }
102         }
103     }
104     return 0;
105 }

FZU 2208

数论题,不会

FZU 2209

分层图。

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <string>
  5 #include <string.h>
  6 #include <stdio.h>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <set>
 11 #include <cmath>
 12 #include <ctime>
 13 #include <cassert>
 14 #include <sstream>
 15 using namespace std;
 16
 17 const int N=501;
 18 const int INF=0x3f3f3f3f;
 19 int get(int n,int u,int k) {
 20     return k*n+u;
 21 }
 22 struct Edge {
 23     int to,next,len;
 24     Edge() {}
 25     Edge(int _to,int _next,int _len):to(_to),next(_next),len(_len) {}
 26 } edge[250000];
 27 int idx=1,head[N];
 28 inline void addedge(int u,int v,int l) {
 29     edge[++idx]=Edge(v,head[u],l);
 30     head[u]=idx;
 31 }
 32 int dis[N][N],in[N];
 33 bool vis[N];
 34 bool spfa(int s,int n,int *dis) {
 35     fill(dis,dis+N,INF);
 36     memset(vis,false,sizeof(vis));
 37     memset(in,0,sizeof(in));
 38     dis[s]=0;
 39     vis[s]=true;
 40     queue<int> que;
 41     que.push(s);
 42     in[s]=1;
 43     while (!que.empty()) {
 44         int u=que.front();
 45         que.pop();
 46         vis[u]=false;
 47         for (int k=head[u];k;k=edge[k].next) {
 48             int v=edge[k].to;
 49             if (dis[v]>dis[u]+edge[k].len) {
 50                 dis[v]=dis[u]+edge[k].len;
 51                 if (!vis[v]) {
 52                     vis[v]=true;
 53                     in[v]++;
 54                     if (in[v]>n) return false;
 55                     que.push(v);
 56                 }
 57             }
 58         }
 59     }
 60     return true;
 61 }
 62 int main () {
 63     //freopen("out.txt","r",stdin);
 64     int T;
 65     scanf("%d",&T);
 66     for (int cas=1;cas<=T;cas++) {
 67         int n,m,k;
 68         scanf("%d %d %d",&n,&m,&k);
 69         idx=1;memset(head,0,sizeof head);
 70         for (int i=1;i<=m;i++) {
 71             int u,v;
 72             scanf("%d %d",&u,&v);
 73             int d;
 74             for (int i=0;i<24;i++) {
 75                 scanf("%d",&d);
 76                 int uu=get(n,u,i);
 77                 int vv=get(n,v,(i+d)%24);
 78                 addedge(uu,vv,d);
 79                 uu=get(n,v,i);
 80                 vv=get(n,u,(i+d)%24);
 81                 addedge(uu,vv,d);
 82             }
 83         }
 84         for (int i=0;i<24;i++) {
 85             spfa(get(n,1,i),n*24,dis[i]);
 86         }
 87         printf("Case #%d:",cas);
 88         while (k--) {
 89             int v,s;
 90             scanf("%d %d",&v,&s);
 91             //cout<<"from "<<get(n,1,s)<<endl;
 92             int ret=0x3f3f3f3f;
 93             for (int i=0;i<24;i++) {
 94                 int p=get(n,v,i);
 95                 ret=min(ret,dis[s][p]);
 96             }
 97             if (ret==0x3f3f3f3f) ret=-1;
 98             printf(" %d",ret);
 99         }
100         puts("");
101     }
102     return 0;
103 }

FZU 2210

建立一个虚拟节点,连向所有粮仓,枚举所有禁止的城市,从虚拟节点dfs,更新答案。

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 #include <string>
 5 #include <string.h>
 6 #include <stdio.h>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <set>
11 #include <cmath>
12 #include <ctime>
13 #include <cassert>
14 #include <sstream>
15 using namespace std;
16
17 const int N=2001;
18
19 vector<int>e[N];
20 int in[N];
21 bool vis[N];
22 int fob;
23 int cnt;
24 void dfs(int u) {
25     if (u==fob||vis[u]) return;
26     vis[u]=true;cnt++;
27     for (int i=0;i<e[u].size();i++) {
28         int v=e[u][i];
29         dfs(v);
30     }
31 }
32 int main () {
33     int n,m;
34     while (scanf("%d %d",&n,&m)!=EOF) {
35         for (int i=0;i<=n;i++){
36             e[i].clear();
37             in[i]=0;
38         }
39         for (int i=1;i<=m;i++) {
40             int u,v;
41             scanf("%d %d",&u,&v);
42             e[u].push_back(v);
43             in[v]++;
44         }
45         for (int i=1;i<=n;i++) {
46             if (in[i]==0)
47                 e[0].push_back(i);
48         }
49         int ret=n+1,val=0;
50         for (int i=n;i>=1;i--) {
51             fob=i;
52             memset(vis,false,sizeof vis);
53             cnt=0;
54             dfs(0);
55             cnt--;
56             if (n-cnt>=val) {
57                 val=n-cnt;
58                 ret=i;
59             }
60         }
61         cout<<ret<<endl;
62     }
63     return 0;
64 }

FZU 2211

费用流,把所有蘑菇拆成两个点,根据时间关系,互相连边。农田的限制在于源点出来的流的大小。

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <string>
  5 #include <string.h>
  6 #include <stdio.h>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <set>
 11 #include <cmath>
 12 #include <ctime>
 13 #include <cassert>
 14 #include <sstream>
 15 using namespace std;
 16
 17 const int N=5010;
 18 const int INF=0x3f3f3f3f;
 19
 20 struct Edge{
 21     int to,next,f;
 22     long long c;
 23     Edge(){}
 24     Edge(int _to,int _nxt,int _f,long long _c):to(_to),next(_nxt),f(_f),c(_c){}
 25 }edge[N<<2];
 26
 27 int head[N],idx;
 28 bool vis[N];
 29 long long dis[N];
 30 int pree[N],prev[N];
 31 void addedge(int u,int v,int flow,long long cost){
 32     edge[++idx]=Edge(v,head[u],flow,cost);
 33     head[u]=idx;
 34     edge[++idx]=Edge(u,head[v],0,-cost);
 35     head[v]=idx;
 36 }
 37 bool spfa(int s,int e){
 38     memset(vis,0,sizeof(vis));
 39     memset(pree,-1,sizeof(pree));
 40     memset(prev,-1,sizeof(prev));
 41     for (int i=0;i<N;i++) dis[i]=~0ULL>>3;
 42     dis[s]=0;
 43     vis[s]=true;
 44     queue<int>que;
 45     que.push(s);
 46     while (!que.empty()){
 47         int cur=que.front();
 48         que.pop();
 49         vis[cur]=false;
 50         for (int k=head[cur];k;k=edge[k].next){
 51             if (edge[k].f){
 52                 int n=edge[k].to;
 53                 if (dis[n]>dis[cur]+edge[k].c){
 54                     dis[n]=dis[cur]+edge[k].c;
 55                     prev[n]=cur;
 56                     pree[n]=k;
 57                     if (!vis[n]){
 58                         vis[n]=true;
 59                         que.push(n);
 60                     }
 61                 }
 62             }
 63         }
 64     }
 65     if (dis[e]>=INF) return 0;
 66     return 1;
 67 }
 68 long long minCostMaxFlow(int src,int sink){
 69     long long cur,min_val;
 70     long long ansf=0,ansc=0;
 71     while (spfa(src,sink)){
 72          cur=sink;
 73          min_val=INF;
 74          while (prev[cur]!=-1){
 75             if (min_val>edge[pree[cur]].f)
 76                 min_val=edge[pree[cur]].f;
 77             cur=prev[cur];
 78          }
 79          cur=sink;
 80          while (prev[cur]!=-1){
 81             edge[pree[cur]].f-=min_val;
 82             edge[pree[cur]^1].f+=min_val;
 83             cur=prev[cur];
 84          }
 85          ansc+=dis[sink]*min_val;
 86          ansf+=min_val;
 87     }
 88     return ansc;
 89 }
 90
 91 int s[N],t[N],v[N];
 92 int main () {
 93     int T;
 94     scanf("%d",&T);
 95     for (int cas=1;cas<=T;cas++) {
 96         int n,m;
 97         scanf("%d %d",&n,&m);
 98         for (int i=1;i<=m;i++) {
 99             scanf("%d %d %d",s+i,t+i,v+i);
100         }
101         idx=1;memset(head,0,sizeof head);
102         for (int i=1;i<=m;i++) {
103             for (int j=1;j<=m;j++) {
104                 if (t[i]<s[j]) {
105                     addedge(i+m,j,INF,0);
106                 }
107             }
108         }
109         int s=m+m+1,t=m+m+1+1;
110         for (int i=1;i<=m;i++) {
111             addedge(0,i,INF,0);
112             addedge(i,i+m,1,-v[i]);
113             addedge(i+m,t,INF,0);
114         }
115         addedge(s,0,n,0);
116         long long ret=-minCostMaxFlow(s,t);
117         cout<<ret<<endl;
118     }
119     return 0;
120 }

时间: 2024-10-11 02:54:28

FOJ 11月月赛题解的相关文章

csu-2018年11月月赛Round2-div2题解

csu-2018年11月月赛Round2-div2题解 A(2193):昆虫繁殖 Description 科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强.每对成虫过x个月产y对卵,每对卵要过两个月长成成虫.假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后的第一个月不产卵(过X个月产卵),问过Z个月以后,共有成虫多少对?0=<X<=20,1<=Y<=20,X=<Z<=50 Input 单组数据 x,y,z的数值 Output 过Z个月以后,共有成虫对

csu-2018年11月月赛Round2-div1题解

csu-2018年11月月赛Round2-div1题解 A(2191):Wells的积木游戏 Description Wells有一堆N个积木,标号1~N,每个标号只出现一次 由于Wells是手残党,所以每次只能取出一块积木放在积木顶层 现在Wells想知道至少需要操作几次可以把积木堆成从顶至底标号升序 不论什么都很菜的Wells显然不知道怎么做 所以作为人生赢家的你义不容辞的决定帮助可怜的Wells Input 第一行一个正整数N 接下来N行,从顶至底描述每块积木的标号 Output 输出一行

USACO银组12月月赛题解

USACO银组12月月赛题解 Convention 题面 一场别开生面的牛吃草大会就要在Farmer John的农场举办了! 世界各地的奶牛将会到达当地的机场,前来参会并且吃草.具体地说,有N头奶牛到达了机场(1≤N≤105),其中奶牛i在时间ti(0≤ti≤109)到达.Farmer John安排了M(1≤M≤105)辆大巴来机场接这些奶牛.每辆大巴可以乘坐C头奶牛(1≤C≤N).Farmer John正在机场等待奶牛们到来,并且准备安排到达的奶牛们乘坐大巴.当最后一头乘坐某辆大巴的奶牛到达的

洛咕11月月赛部分题解 By cellur925

听说是你谷史上最水月赛?我不听我最菜 T1:终于结束的起点 月天歌名好评 给你一个模数 \(M\),请你求出最小的 \(n > 0\),使得\(fib(n)\) \(mod\) \(m=0\),\(fib(n+1)\) \(mod\) \(m=1\). 数学题,开始还想打表验证下,但是我不会告诉你我打表的时候没有很及时地取膜,然后中间有结果溢出,耽误了很长时间,企图找了很久规律.结果发现暴力就能过.hhh. 这个故事告诉我们要及时取膜! #include<cstdio> #include

洛谷11月月赛round.1

太感动了#2 thwfhk 240 (801ms) 100 100 40 又一张明信片,话说10月的怎么还没收到 P2246 SAC#1 - Hello World(升级版) 题目背景 一天,智障的pipapi正在看某辣鸡讲义学程序设计. 题目描述 在讲义的某一面,他看见了一篇文章.这篇文章由英文字母(大小写均有).数字.和空白字符(制表/空格/回车)构成. pipapi想起了他最近刚刚学会写的Hello World程序.他非常好奇,这篇文章中,“HelloWorld”作为子序列到底出现过多少次

11月下旬题解

(压根就没做几道题,无地自容QAQ) gym101138 J 直接上树链剖分+线段树,注意处理好端点问题(其实有(Q+N)logN的做法) 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 struct way{int po,next;} e[200010]; 6 struct node{ll lm,rm,s,mx;} tr[100010*4]; 7 int s[100010],a[1000

11月月赛

A-HDU1087   http://acm.hdu.edu.cn/showproblem.php?pid=1087 相当于从数组a中找一个最优序列,我们设要找的序列为A,序列A满足两个条件,一是A中的元素大小满足单调递增,二是A中所有元素的和最大,输出这个最大值. 令f[i]表示以第i个元素结尾的A序列的最大值,则有f[i]=MAX{ f[j]+a[i]  |  j<i }   ans=MAX{f[i]}; 1 *#include<bits/stdc++.h> 2 using name

code+11月月赛

T1 SB题 1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<ctime> 5 #include<iostream> 6 #include<algorithm> 7 #include<queue> 8 #include<set> 9 #define inf (0x7fffffff) 10 #define l(a) ((a)&

FZU 11月月赛D题:双向搜索+二分

/* 双向搜索感觉是个不错的技巧啊 */ 题目大意: 有n的物品(n<=30),平均(两个人得到的物品差不能大于1)分给两个人,每个物品在每个人心目中的价值分别为(vi,wi) 问两人心目中的价值差最小是多少. 分析: 直接暴搜目测会超时 想到先搜索前一半,用数组a[0][i]保存第一个人在前半段取 i 个物品两个人的差的所有情况: 再搜索后一半保存两个人的差的相反数,用相同的规则保存在a[1][]中. 要想总差最小只需要 a[0][i]-a[1][num-i] (num=n/2或 n/2+1)