抽空在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 }