昨天的訓練題。
A。有關網絡流的最大流問題,並不懂。
UVA 753 A Plug for UNIX
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
using namespace std;
typedef char str[31];
const int N=105;
const int MAX=2147483647;
int T,tot,n,m,q,i,j,l,r,u,v,ans,sum,head[N<<3],Next[N*N],go[N*N],cost[N*N],down[N*N],b[N*N],d[N<<3];
str s1,s2,s[N<<3];
inline int S(int a,int b) { return (a<b)?a:b; }
inline void Add(int u,int v,int t)
{ Next[++l]=head[u],head[u]=l,go[l]=v,cost[l]=t,down[l]=l+1;
Next[++l]=head[v],head[v]=l,go[l]=u,cost[l]=0,down[l]=l-1;
}
inline int Find(str A)
{ if (r==0) { strcpy(s[r=1],A); return r; }
for (int i=1;i<=r;i++)
if (strcmp(s[i],A)==0) return i;
strcpy(s[++r],A);
return r;
}
inline bool bfs()
{ int l,r,j; b[l=r=1]=0; memset(d,-1,sizeof(d)); d[0]=0;
while (l<=r)
{ for (j=head[b[l]];j;j=Next[j])
if ((cost[j])&&(d[go[j]]==-1)) d[go[j]]=d[b[l]]+1,b[++r]=go[j]; l++;
} if (d[800]>0) return true; return false;
}
inline int dinic(int st,int tk)
{ if (st==800) return tk; int wc=tk,j,kcm;
for (j=head[st];j&&tk;j=Next[j])
if ((d[go[j]]>d[st])&&(cost[j]))
{ kcm=dinic(go[j],S(tk,cost[j]));
cost[j]-=kcm; cost[down[j]]+=kcm; tk-=kcm;
}
return wc-tk;
}
int main()
{ freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
for (scanf("%d",&T),tot=1;tot<=T;tot++)
{ memset(head,0,sizeof(head));
if (tot>1) printf("\n");
scanf("%d",&n),l=ans=r=0;
for (i=1;i<=n;i++)
{ scanf("%s",s1);
u=Find(s1);
Add(u,800,1);
}
scanf("%d",&m);
for (i=1;i<=m;i++)
{ scanf("%s%s",s1,s2);
u=Find(s1),v=Find(s2);
Add(u,v,1),Add(0,u,1);
}
scanf("%d",&q);
for (i=1;i<=q;i++)
{ scanf("%s%s",s1,s2);
u=Find(s1),v=Find(s2);
Add(u,v,MAX);
}
while (bfs()) while (sum=dinic(0,MAX)) ans+=sum;
printf("%d\n",m-ans);
}
return 0;
}
C, 雙向隊列模擬。同看不懂。
UVA 732 Cat
給定source及target字符串
Source、target長度一樣
兩個操作
從source首位置開始,字符可以在棧sc中進行入棧,入棧後source中此字符串被去掉,爲了方便深搜,用deque(dc)來保存source。記操作爲i。
從sc出棧到新字符串stem,如果可以組成target,則爲可行解,輸出對棧。記操作爲o。
注意事項
可以從sample觀察到,要從source獲得target,第一個對棧操作必爲I(因此由i進入dfs),最後一個對棧操作必爲I(因此由i操作後中尋找可行解)。
爲了按字典序輸出,因此按字典序搜索。
HDU 3047 Zjnu Stadium
題意:有一個體育館,座位呈環狀,每一列有300個座位,按逆時鐘方向編號爲1~300,假設行數無窮大。
某一天,有N個人來到這個體育館看一場賽事,主辦方提出了M個要求,要求的格式是“A B X”,表示的是,假設A坐在編號爲i的列,則B必須坐在編號爲(i+x)的列上。
這些要求裏有一些是錯誤的,只有和前面的要求產生衝突時纔算錯誤,其它都是正確的。程序要輸出錯誤的要求個數。
分析:帶權並查集
對於並查集中的每一棵數, 樹根的距離爲0,然後以樹根作爲參照,每個結點的權值代表與樹根的距離。
合併A,B時,假設A,B屬於不同的樹,那麼就要合併這兩棵樹, 把A樹合併到B樹上,這時要給A樹的跟結點root_a賦值,關鍵是給root_a附上一個什麼值。 由於A點和B點的權值rank[A]和rank[B]都是相對跟結點的距離,所以分析A,B之間的相對距離,可以得到rank[root_a] = rank[A]+x-rank[B]。 注意到這時,對於原來的A的樹,只跟新了root_a跟結點的權值, 那麼其它結點的更新在查找的那一步裏面實行了。