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 }
View Code

 

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 }
View Code

 

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 }
View Code

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

posted @ 2015-11-25 00:31  活在夢裡  阅读(286)  评论(0编辑  收藏  举报