【AC_LCC_CWJ 第二场】World Final 2006

这场最后太疼了,都是我个人的原因,第一题有些情况没考虑到,于是最后A题这个大水题很遗憾地没过。

一开始师父有事就跑了,大概1个多小时以后又回来了。

这短时间LCC沉浸在G中,我沉浸在J中,貌似都不可自拔

然后后来我觉得J太大自然了,于是又看了一个Board,UESTC的队过了I,然后赶去围观,果断发现是水题,于是切掉。

接下来LCC大神在G题题意极度不清晰的情况下暴力试出了Accepted,Orz。

然后后来又看到了UESTC那队把B过了,我一看,迅速反应出这和昨天那题最大流的构图是一样,只要求个费用流就可以了。

但是第一遍提交的时候出现的很神奇的事情,我交上去Waiting,然后等了N久之后,UESTC也交了一个Waiting,在之后,LCC也交了一个Waiting,我顿时惊叹,题库爆了!然后再过了几秒之后,3个TLE出现,顿时觉得有点假。。。

然后手测了一些数据,发现由于精度问题,费用流跑了正向边以后又去跑反向边去了,然后+个eps以后就Y了。

此期间LCC用小号对E题不断进行轰炸,后来发现是输出的时候格式出了问题…

师父一跑来就说,D是数论,我来切,然后就切掉了~Orz!!!!

接着我看了A题,觉得比较简单,于是开切,然后由于一种情况没有考虑到,应该说题意上有一点误解。

就是这一句

the travel covered by a ticket be completed in order and without intervening travel

然后在我脑海里形成映像,后面的路程也是要完全吻合的,于是悲剧。。。

最后就5题了(B D E G I),师父表示当年WF2006最多的一队也就是6题。我顿时捶胸顿足……就差了我的A题啊

都是我的错……

下面简单说说我做的两题(都超级水):

B题就是要填一个m*n的矩阵c,分别给出每一行和每一列的和,然后每个格子还有一个实数权w,最后输出最小和最大的

Sum{c[i][j]*w[i][j]},有一些实权位-1的表示不可填。然后就是最小费用最大流+最大费用最大流了。

http://acm.hust.edu.cn:8080/judge/contest/viewProblem.action?pid=22056

代码:http://xiudaima.appspot.com/code/detail/4554012

I题就一个Floyd

然后现在把A题补一下。

【题目链接】http://acm.hust.edu.cn:8080/judge/contest/viewProblem.action?pid=22055

就是给定20张机票,每张机票有一条旅行路线和一个价格,每次可以用一张机票路线的前缀,然后给定20个询问,每个询问都是一条路线,问你通过这些机票,最少花多少钱可以完成这条路线。完成这条路线时必须按顺序经过路线上的点,但是在路线的各点中间,你可以先跑去其它地方再飞回来。

【解法】

F[i,j,k]表示已经完成这个路线的前i个点,现在在第j张飞机票的第k个点时,最少的费用是多少。

由于有后效性,用SPFA来转移之。

然后就解决了

【Hint】题目给出的各城市的编号是任意的。。。如果处理的不好要先离散化。一般直接判等于就行。

【CODE】

http://xiudaima.appspot.com/code/detail/4490007

最后Orz LCC、Orz AC,鄙视我自己

[UVALive 4865 Data Recovery] 疼疼最大流

【题目链接】http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=15554

【题目大意】

给定一个m*n的矩阵,矩阵里每个格子填一个[0,100]的数,有些格子被挖空了(用-1表示),让你向里面填数字。再给定每一行和每一列的和。

如果没有解,那么输出-1

有解的情况下,对于那些确定值的格子填出来,不能确定值的格子,用-1代替。

(m,n<=50)

样例1:

Input:

2 2

1 -1           //-1表示被挖空的不确定的位置

-1 -1

100 100      //每行的和都是100

100 100     //每列的和都是100

Output:

1 99

99 1

【算法分析】

首先用点分别代表行和列,然后形成二分图,行列之间的边就对应着格子。

然后加个源汇沙茶建边做一次最大流就可以得到(确定的格子不需要加边,直接对行列和减一下就可以了)。

无解什么的都解决了。

但是判定一个点是否必须填这个值就需要思考一下了。

由于一个流对应一个解,所以解不同对应着流不同。

我们看图中二分图中的红色的那条边:

假如它要减少流量,那么必须要在残余网络中存在类似这样的路径(注意箭头方向):

假如它要增加流量,那么必须要在残余网络中存在类似这样的路径(注意箭头方向):

实际上从残余网络上看,从二分图左边的点集指向右边点集的边可以视为是增加流量的边,从右边点集指向左边点集的边可以视为撤销原流的边。
于是乎,我们判定一条边上面的流值是否一定,只需要看这条边在残余网络中,是否存在一个点数>=3的环(=2的时候显然是没意义的,就是两个点之间跑),包含这条边就可以了。

实现随意,暴力可过。一开始写了个Floyd发现好难搞=2的环的情况,于是改回暴力dfs。

复杂度O(m^2*n^2)

【CODE】

#include #include #include #define clr(a) memset(a,0,sizeof(a))
const int N=55;
int m,n,S,T,Flow;
int map[N][N];
int c[N+N][N+N];
int v[N+N];
int v2[N+N];
int L[N+N];
int fa[N+N];
int Sx[N],Sy[N];

void init(){
     int i,j;
     clr(c);
     clr(Sx);
     clr(Sy);
     scanf("%d%d",&m,&n);
     for (i=1;i<=m;i++)
       for (j=1;j<=n;j++){
         scanf("%d",&map[i][j]);
         if (map[i][j]!=-1){
           Sx[i]-=map[i][j];
           Sy[j]-=map[i][j];
         }
         else c[i][j+m]=100;
       }
     for (i=1;i<=m;i++){int x; scanf("%d",&x); Sx[i]+=x;}
     for (i=1;i<=n;i++){int x; scanf("%d",&x); Sy[i]+=x;}
}

void build(){
     int i,j;
     S=m+n+1;
     T=m+n+2;
     for (i=1;i<=m;i++) c[S][i]=Sx[i];
     for (i=1;i<=n;i++) c[i+m][T]=Sy[i];
}

bool bfs(){
     int head=0,tail=1,i,j;
     for (i=1;i<=T;i++) v[i]=0;
     L[1]=S;
     v[S]=1;
     while (head!=tail){
           head++;
           for (i=1;i<=T;i++)
             if (c[L[head]][i]>0 && v[i]==0){
               v[i]=1;
               L[++tail]=i;
               fa[i]=L[head];
               if (i==T) return true;
             }
     }
     return false;
}

void change(){
     int nf=0x7FFFFFFF;
     for (int i=T;i!=S;i=fa[i])
       if (c[fa[i]][i]     for (int i=T;i!=S;i=fa[i]){
         c[fa[i]][i]-=nf;
         c[i][fa[i]]+=nf;
     }
     Flow+=nf;
}

void Edmonds_Karp(){
     Flow=0;
     while (bfs())
       change();
}

bool check(){
     int Sum=0;
     for (int i=1;i<=m;i++) Sum+=Sx[i];
     if (Sum!=Flow) return false;
     Sum=0;
     for (int i=1;i<=n;i++) Sum+=Sy[i];
     if (Sum!=Flow) return false;
     return true;
}

void dfs(int p){
     v[p]=1;
     int i;
     for (i=1;i<=m+n;i++){
         if (p==S && i==T || p==T && i==S) continue;
         if (c[p][i]>0 && !v[i]) dfs(i);
     }
}

void solve(){
     if (!check()){puts("-1"); return;}
     int i,j,k,l;
     for (i=1;i<=m;i++)
       for (j=m+1;j<=m+n;j++)if (map[i][j-m]==-1){
           S=i; T=j;
           for (k=1;k<=m+n;k++) v[k]=0;
           bool flag=false;
           if (c[i][j]>0){
             dfs(T);
             if (v[S]==1) flag=true;
           }
           if (!flag && c[j][i]>0){
             for (k=1;k<=m+n;k++) v[k]=0;
             dfs(S);
             if (v[T]==1) flag=true;
           }
           if (!flag) map[i][j-m]=c[j][i];
       }
     for (i=1;i<=m;i++)
       for (j=1;j<=n;j++){
           printf("%d",map[i][j]);
           if (j==n) putchar(‘n’);
                else printf(" ");
       }
}

int main(){
    while (1){
          init();
          if (n+m==0) break;
          build();
          Edmonds_Karp();
          solve();
    }
    return 0;
}
【Others】

今天和AC、LCC做了一场比赛,我队累计切了10题,我显然属于打杂类型……水了4个题,难的都他们去搞了。

Mark一下这四道水题,以后出给小朋友还是可以的

C

http://acm.hust.edu.cn:8080/judge/contest/viewProblem.action?pid=22045

代码:http://xiudaima.appspot.com/code/detail/4568015

状压dp,各种合并

D

http://acm.hust.edu.cn:8080/judge/contest/viewProblem.action?pid=22046

代码:http://xiudaima.appspot.com/code/detail/4514015

模拟

K

http://acm.hust.edu.cn:8080/judge/contest/viewProblem.action?pid=22053

代码:http://xiudaima.appspot.com/code/detail/4572008

DP,需要转一下思路

L

http://acm.hust.edu.cn:8080/judge/contest/viewProblem.action?pid=22054

代码:http://xiudaima.appspot.com/code/detail/4442019

想出了n^2 per data的,直接交超时,于是打表交。因为表才1000,所以程序并不是很长,上面的代码是用来打表的。其实这个预处理可以放在程序前面,不过需要变一下,降为n^2。当时没怎么想到就直接n^3地打表了。

HDU月赛——2010.5.1

本次月赛出了6题。Rank 2。
1002果断TLE。然后再用拓展欧几里得算法,再次WA到死。
然后最后rejudge了。
回文数的正解居然是要排序的,我写的是按顺序弄出来的。。。一路狂WA。。。
最后就这样悲剧了。
悲剧+沙茶。。。
没啥说的。。。BS我这沙茶吧
1001:http://hi.baidu.com/edwardmj/blog/item/7973c631706b6af41a4cff36.html
1002:http://hi.baidu.com/edwardmj/blog/item/432eec95b9c7bc6155fb9628.html
1003:http://hi.baidu.com/edwardmj/blog/item/bdd0b333ad4f3215ebc4af59.html
1004:http://hi.baidu.com/edwardmj/blog/item/b40d62d19d4bc038970a1612.html
1005:http://hi.baidu.com/edwardmj/blog/item/82fcbcc49ecc4f179d163d21.html
1006:http://hi.baidu.com/edwardmj/blog/item/46f4fcd30c4a34349b5027e2.html
1007:http://hi.baidu.com/edwardmj/blog/item/ddefd41529d7340d4a90a71c.html
另外1003在SCOI测试中,匹配是比并查集快的,但是这里匹配会TLE,只能用并差集。

ZOJ比赛——2010.4.17

本次比赛由我和CZM一起参加。
先贴提交记录:
Run ID Submit Time Judge Status Problem ID Language Run Time(ms) Run Memory(KB) User Name 3470 2010-04-17 16:19:45 Accepted K C++ 130 220 CWJ&&CZM 2991 2010-04-17 15:35:34 Accepted J C++ 890 13752 CWJ&&CZM 1496 2010-04-17 13:46:15 Accepted E FPC 20 28 CWJ&&CZM 1188 2010-04-17 13:28:52 Wrong Answer E FPC 20 28 CWJ&&CZM 1085 2010-04-17 13:20:44 Accepted G C++ 0 176 CWJ&&CZM 596 2010-04-17 12:50:55 Accepted B C++ 0 176 CWJ&&CZM 463 2010-04-17 12:45:57 Accepted L C++ 0 176 CWJ&&CZM 311 2010-04-17 12:41:33 Accepted A C++ 0 176 CWJ&&CZM
首先一开场,CZM没在,于是我AC3道水题:A、B、L。
然后CZM上了,然后兵分两路,他做E,我做K。
然后他说E题十分水。
然后我看了一下K以后,发现和SGU122很像,但是又略有不同,然后想留着后面做算了。
于是我看到G题,一大堆英文和五行的,什么都没看懂。
绝望之际,随便交了个n/2,居然AC了!
。。。十分无语
然后CZM的E题WA了一次,然后还是AC了。
于是我开始YY J题。
一看。。。恩,感觉应该是以i划分状态,然后f[i,j,k]表示第i个完成,A处理器末时间为j,B处理器末时间为k的时候能否做到。当我看到我的f是布尔型的时候,觉得有些搞笑。。。于是换成f[i,j]表示第i个任务完成,A处理器末时间为j,B处理器末时间最小能是多少。
然后将sum猥琐优化一下,1Y,不过这个时间确实挺难看。。。
然后我们两个最后再来搞K题,讨论了半天,CZM觉得他的构造法是对的,我表示没听懂~
我想的是费用流,写了没几行,突然想起费用流不能有环。。。
于是我想用度数预处理一下暴力,CZM继续做他的构造法。
然后我的AC,他用小号交WA了。。。
我的做法是:选取出度最大的一个点做起点,然后DFS即可。
因为图是接近完全图,所以搜出来也很正常。。。
然后,我想暴力C题,最后没时间,比赛结束。
最后我们过了7题。
rank:22
排名围观地址:http://acm.zju.edu.cn/onlinejudge/showContestRankList.do?contestId=308

现在说说AC的两道不算太弱智的题目,现在贴贴简单的解题报告和程序:
J:F[i,j]表示完成第i个任务,A处理器末时间为j时,B处理器末时间最小为多少。然后转移即可。
K:由于每个点的出度+入度=n-1,于是把出度最大的那个当起点,暴力DFS即可。当然也可以DLX。
【CODE For J】
#include using namespace std;
const int N=105;
const int INF=100000000;
int Tc,n;
int a[N],b[N],tail[N];
int F[N][N*N];
int list[N][N*N*2];

void init(){
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);
}

int solve(){
int i,j,k,sum=0,*f;
a[n+1]=0;
for (i=1;i<=n+1;i++){
sum+=a[i];
for (j=0;j<=sum;j++)
F[i][j]=INF;
}
F[1][0]=0;
sum=0;
for (i=1;i<=n;i++){
f=F[i+1];
for (j=0;j<=sum;j++)
if (F[i][j]!=INF){
f[j+a[i]]=min(f[j+a[i]],max(F[i][j],j));
f[max(j,F[i][j])]=min(f[max(j,F[i][j])],F[i][j]+b[i]);
}
sum+=a[i];
}
int ans=INF;
for (j=0;j<=sum;j++)
ans=min(ans,max(j,F[n+1][j]));
return ans;
}

int main(){
scanf("%d",&Tc);
for (int i=1;i<=Tc;i++){
init();
cout << solve() << endl;
}
}

【CODE For K】
#include #include #include const int N=105;
int n,S,step;
int din[N],dout[N],a[N][N],v[N],list[N];
bool flag;

void init(){
scanf("%d",&n);
memset(din,0,sizeof(din));
memset(dout,0,sizeof(dout));
memset(a,0,sizeof(a));
int i,j,x,y;
for (i=1;i<=n*(n-1)/2;i++){
scanf("%d%d",&x,&y);
a[x][y]=1;
din[y]++;
dout[x]++;
}
}

void dfs(int i){
v[i]=1;
step++;
list[step]=i;
if (step==n){
flag=true;
return;
}
for (int j=1;j<=n;j++)
if (a[i][j] && !v[j]){
dfs(j);
if (flag) return;
}
step–;
v[i]=0;
}

void work(){
if (n==1){
printf("1n");
return;
}
S=1;
for (int i=1;i<=n;i++)
if (dout[i]>dout[S]) S=i;
memset(v,0,sizeof(v));
flag=false;
step=0;
dfs(S);
if (!flag) printf("Impossiblen");
else
for (int i=1;i<=n;i++){
printf("%d",list[i]);
if (i!=n) printf(" ");
else printf("n");
}
}

int main(){
int Tc;
scanf("%d",&Tc);
for (int i=1;i<=Tc;i++){
init();
work();
}
}

ZOJ比赛——2010.4.10

这次比赛首先说肥闽是来打酱油的。。。
他一题都没出,果然是酱油君。(上一次好像也是)

下面发一段他说的话:
徒弟  18:56:08
还不是你们两只……都把水题a了……一题也不剩给我,bs
徒弟  18:56:29
明明3道水题……应该1人一道……或者你不做才对的嘛
徒弟  18:56:38
抢哥的水题……日……

说说比赛流程:
首先FHN前40分钟秒了A和E。除了Orz我还能说什么呢。。。

然后这之后我这个水B居然在最后一题上WA了1次。为什么呢?原因是如果N!=M的时候,我没有把边读完
好吧,1WA,1A。
然后,我去搞第三题。因为当时看了一下,觉得比较有FEEL。但是看看AC人数:1。
但是我还是上了。。。
于是——1A。。。哈哈。。。我还是这题程序速度最快的那个。
然后,肥闽和FHN,已经把F题的题意参详出来了。
他们表示没啥想法,我一看。。。这题根本我就做过= =。
而且那题数据规模还大一些,但是建图有点不同而已。
于是迅速敲完,5题搞定。
值得注意的是:肥闽一直在搞第二题,但是他直到酱油瓶都满了,还没有AC,最后,我们悲剧地停在5题上。。。
最后rank:22
http://acm.zju.edu.cn/onlinejudge/showContestRankList.do?contestId=307
排名围观地址。。。
最后总结:这次没有到6,ULT没有出来就GG了,主要原因是:肥闽