題目地址:HDU 4975
對這題簡直無語。。。本來以爲這題要用什麼更先進的方法,結果還是老方法,這麼卡時間真的好嗎。。。。比賽的時候用了判環的方法,一直TLE。。後來換了矩陣DP的方式,加了加剪枝就過了。。無語了。。
代碼如下:
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <iostream>
- #include <cstdio>
- #include <string>
- #include <cstring>
- #include <stdlib.h>
- #include <math.h>
- #include <ctype.h>
- #include <queue>
- #include <map>
- #include <set>
- #include <algorithm>
- using namespace std;
- const int INF=0x3f3f3f3f;
- int head[1010], source, sink, nv, cnt, vis[610][600], mp[600][600];
- int cur[1010], num[1010], d[1010], pre[1010];
- int a[600], b[600];
- struct node
- {
- int u, v, cap, next;
- } edge[1000000];
- void add(int u, int v, int cap)
- {
- edge[cnt].v=v;
- edge[cnt].cap=cap;
- edge[cnt].next=head[u];
- head[u]=cnt++;
- edge[cnt].v=u;
- edge[cnt].cap=0;
- edge[cnt].next=head[v];
- head[v]=cnt++;
- }
- void bfs()
- {
- memset(num,0,sizeof(num));
- memset(d,-1,sizeof(d));
- queue<int>q;
- q.push(sink);
- d[sink]=0;
- num[0]=1;
- while(!q.empty())
- {
- int u=q.front();
- q.pop();
- for(int i=head[u]; i!=-1; i=edge[i].next)
- {
- int v=edge[i].v;
- if(d[v]==-1)
- {
- d[v]=d[u]+1;
- num[d[v]]++;
- q.push(v);
- }
- }
- }
- }
- int isap()
- {
- memcpy(cur,head,sizeof(cur));
- int flow=0, u=pre[source]=source, i;
- bfs();
- while(d[source]<nv)
- {
- if(u==sink)
- {
- int f=INF, pos;
- for(i=source; i!=sink; i=edge[cur[i]].v)
- {
- if(f>edge[cur[i]].cap)
- {
- f=edge[cur[i]].cap;
- pos=i;
- }
- }
- for(i=source; i!=sink; i=edge[cur[i]].v)
- {
- edge[cur[i]].cap-=f;
- edge[cur[i]^1].cap+=f;
- }
- flow+=f;
- u=pos;
- }
- for(i=cur[u]; i!=-1; i=edge[i].next)
- {
- if(d[edge[i].v]+1==d[u]&&edge[i].cap)
- break;
- }
- if(i!=-1)
- {
- cur[u]=i;
- pre[edge[i].v]=u;
- u=edge[i].v;
- }
- else
- {
- if(--num[d[u]]==0) break;
- int mind=nv;
- for(i=head[u]; i!=-1; i=edge[i].next)
- {
- if(mind>d[edge[i].v]&&edge[i].cap)
- {
- mind=d[edge[i].v];
- cur[u]=i;
- }
- }
- d[u]=mind+1;
- num[d[u]]++;
- u=pre[u];
- }
- }
- return flow;
- }
- bool panduan(int n,int m)
- {
- memset(vis,0,sizeof(vis));
- int i, j, k;
- for(i=1;i<=n;i++)
- {
- if(a[i]==0||a[i]==9*m) continue ;
- for(j=1;j<=m;j++)
- {
- if(b[j]==0||b[j]==9*n) continue ;
- for(k=j+1;k<=m;k++)
- {
- int t1=0, t2=0;
- if(mp[i][j]&&mp[i][k]!=9)
- {
- if(vis[j][k]) return 1;
- t1=1;
- }
- if(mp[i][k]&&mp[i][j]!=9)
- {
- if(vis[k][j]) return 1;
- t2=1;
- }
- if(t1) vis[k][j]=1;
- if(t2) vis[j][k]=1;
- }
- }
- }
- return 0;
- }
- int read()
- {
- int x = 0;
- char ch = ' ';
- 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, i, j, n, m, sum1, sum2, num=0;
- t=read();
- while(t--)
- {
- num++;
- n=read();
- m=read();
- sum1=sum2=0;
- memset(head,-1,sizeof(head));
- cnt=0;
- source=0;
- sink=n+m+1;
- nv=sink+1;
- for(i=1; i<=n; i++)
- {
- a[i]=read();
- sum1+=a[i];
- }
- for(i=1; i<=m; i++)
- {
- b[i]=read();
- sum2+=b[i];
- }
- printf("Case #%d: ",num);
- if(sum1!=sum2)
- {
- puts("So naive!");
- continue ;
- }
- for(i=1; i<=n; i++)
- {
- add(source,i,a[i]);
- for(j=1; j<=m; j++)
- {
- add(i,j+n,9);
- }
- }
- for(i=1; i<=m; i++)
- {
- add(i+n,sink,b[i]);
- }
- int ans=isap();
- if(ans!=sum1)
- {
- puts("So naive!");
- continue ;
- }
- for(i=1;i<=n;i++)
- {
- for(j=head[i];j!=-1;j=edge[j].next)
- {
- int v=edge[j].v;
- if(v>n&&v<=n+m)
- mp[i][v-n]=9-edge[j].cap;
- }
- }
- if(panduan(n,m))
- {
- puts("So young!");
- }
- else
- puts("So simple!");
- }
- return 0;
- }