17-11-01模拟赛

T1:

倍增处理x到y是否能通过2i的引导力到达。如果可以,则连由x向y的边。

而后对连边从s到做bfs即可。注意判断无解的情况。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define LG 35
 5 #define MN 53
 6 using namespace std;
 7 inline int in(){
 8     int x=0;bool f=0; char c;
 9     for (;(c=getchar())<'0'||c>'9';f=c=='-');
10     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
11     return f?-x:x;
12 }
13 bool vis[LG][MN][MN],mk;
14 int dis[MN],q[MN<<1];
15 int n,m,p,s,t,x,y,head,tail;
16 inline void floyd(){
17     for (int l=2;l<=p;++l)
18     for (int k=1;k<=n;++k)
19     for (int i=1;i<=n;++i)
20     for (int j=1;j<=n;++j) vis[l][i][j]|=(vis[l-1][i][k]&&vis[l-1][k][j]);
21 }
22 int main()
23 {
24     n=in();m=in();p=in();s=in();t=in();
25     for (int i=1;i<=m;++i){
26         x=in();y=in();vis[1][y][x]=1;
27     }floyd();head=tail=1;q[1]=s;dis[s]=1;
28     while (head<=tail){
29         int u=q[head];++head;if (u==t){mk=1;break;}
30         for (int v=1;v<=n;++v)if (!dis[v]){
31             for (int j=1;j<=p;++j)
32             if (vis[j][u][v]) {dis[v]=dis[u]+1;q[++tail]=v;break;}
33         }
34     }printf("%d",mk?dis[t]-1:-1);return 0;
35 }

T2:考虑能使主对角线均为黑格时,可以从每行恰好取一个黑格,使得黑格遍历所有列。

考虑对行与列进行匹配,行向列连边,转化为二分图匹配问题。使用匈牙利算法或网络流解决。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 #define clr(x) memset(x,0,sizeof(x))
 6 #define inf 0x7fffffff
 7 #define ME 100005
 8 #define MN 405
 9 using namespace std;
10 inline int in(){
11     int x=0;bool f=0; char c;
12     for (;(c=getchar())<'0'||c>'9';f=c=='-');
13     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
14     return f?-x:x;
15 }
16 struct edge{
17     int to,next,cap;
18 }e[ME];
19 int head[MN],iter[MN],lev[MN];
20 int T,n,cnt=1,s,t,a;
21 inline void ins(int x,int y,int cp){
22     e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt;e[cnt].cap=cp;
23     e[++cnt].to=x;e[cnt].next=head[y];head[y]=cnt;e[cnt].cap=0;
24 }
25 inline void bfs(){
26     queue<int>q;memset(lev,-1,sizeof(lev));
27     q.push(s);lev[s]=0;
28     while (!q.empty()){
29         int u=q.front();q.pop();
30         for (int i=head[u];i;i=e[i].next){
31             int v=e[i].to;
32             if (lev[v]==-1&&e[i].cap>0)
33             lev[v]=lev[u]+1,q.push(v);
34         }
35     }
36 }
37 inline int dfs(int u,int f){
38     if (u==t) return f;int used=0;
39     for (int &i=iter[u];i;i=e[i].next){
40         int v=e[i].to;
41         if (lev[u]<lev[v]&&e[i].cap>0){
42             int w=dfs(v,min(f-used,e[i].cap));
43             if (w>0){
44                 e[i].cap-=w;e[i^1].cap+=w;used+=w;
45                 if (f==used) return f;
46             }
47         }
48     }return used;
49 }
50 inline int dinic(){
51     int fl=0;while (1){
52         bfs();if (lev[t]==-1) return fl;
53         memcpy(iter,head,sizeof(head));
54         int d=0;while ((d=dfs(s,inf))>0) fl+=d;
55     }
56 }
57 inline void init(){
58     clr(lev);clr(head);clr(iter);
59     clr(e);s=t=0;cnt=1;
60 }
61 int main()
62 {
63     T=in();while (T--){
64         n=in();init();s=(n<<1)+1;t=(n<<1)+2;
65         for (int i=1;i<=n;++i)
66         for (int j=1;j<=n;++j){
67             a=in();if (a) ins(i,j+n,inf);
68         }for (int i=1;i<=n;++i) ins(s,i,1),ins(i+n,t,1);
69         puts((dinic()==n)?"Yes":"No");
70     }return 0;
71 }

T3:考虑dp.

离散每个点。可以发现,当两点x,y间距离大于值z时,当gcd(di)|y时,x 总能转移到x+y。实际上,z 可能的最大值为7*8=56。

求出所有d的gcd,不计算不是gcd的倍数的格子,对距离较远的宝石进行距离上的压缩。

如果它们之间的距离大于z,把距离压到z 值附近。dp即可。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define ll long long
 5 #define inf 0x7f7f7f7f7f7f7f7fll
 6 #define MN 100005
 7 #define MM 11000005
 8 using namespace std;
 9 inline ll in(){
10     ll x=0;bool f=0; char c;
11     for (;(c=getchar())<'0'||c>'9';f=c=='-');
12     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
13     return f?-x:x;
14 }
15 struct st{
16     ll p,w;
17 }a[MN];
18 ll pos[MN],mx[MN],f[MM],wt[MN],val[MM];
19 bool vis[60];
20 ll d[10],n,m,k,cnt,top,mc,md,mt,dv,ct,cur,res;
21 inline bool cmp(st x,st y){return x.p<y.p;}
22 inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
23 int main()
24 {
25     freopen("tomato.in","r",stdin);
26     freopen("tomato.out","w",stdout);
27     n=in();m=in();k=in();
28     for (int i=1;i<=k;++i) d[i]=in(),dv*=d[i];
29     for (int i=1;i<=k;++i) dv=gcd(dv,d[i]);
30     for (int i=1;i<=m;++i) a[i].p=in(),a[i].w=in();
31     a[++m].p=0;a[m].w=0;sort(a+1,a+m+1,cmp);pos[0]=-1;
32     for (int i=1;i<=m;++i){
33         if (a[i].p%dv) continue;
34         if (a[i].p/dv==pos[cnt]) wt[cnt]+=a[i].w;
35         else pos[++cnt]=a[i].p/dv,wt[cnt]=a[i].w;
36     }mc=inf;vis[0]=1;mt=-1;
37     for (int i=1;i<=k;++i) d[i]/=dv,mc=min(mc,d[i]);
38     for (md=0;;++md){
39         for (int j=1;j<=k;++j) 
40         if (md>=d[j]) vis[md]|=vis[md-d[j]];
41         if (!vis[md]) mt=md;if (md-mt==mc) break;
42     }for (int i=1;i<=k;++i) md=max(md,d[i]+1);
43     md+=8;val[0]=wt[1];cur=0;
44     for (int i=2;i<=cnt;++i){
45         if (pos[i]-pos[i-1]>md) cur+=md+1;
46         else cur+=pos[i]-pos[i-1];val[cur]=wt[i];
47     }memset(f,0x80,sizeof(f));res=f[0]=val[0];
48     for (int i=1;i<=cur;++i){
49         for (int j=1;j<=k;++j) 
50         if (d[j]<=i)f[i]=max(f[i],f[i-d[j]]+val[i]);
51         res=max(res,f[i]);
52     }printf("%lld",res);return 0;
53 }
原文地址:https://www.cnblogs.com/codingutopia/p/test171101.html