Day2 尤拉路,拓撲排序和差分約束
文章目錄
A.BZOJ 3033: 太鼓達人
題目
程式碼
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+50;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int n,t,ans[maxn];
bool used[maxn];
inline bool eular(int x,int k)//x是當前子串的十進位制表示,k是當前查詢次
{
if (used[x]) return 0;
used[x]=1,ans[k]=x&1;//統計答案,&的規則是:有零則零,否則為一,返回末位數字
if (k==t) return 1;//查詢結束
if (eular((x<<1)&(t-1),k+1)) return 1;
if (eular((x<<1|1)&(t-1),k+1)) return 1;//將每個二進位制數看成一個點,將他前面的數刪去,並在它後面加上0/1就能得到兩個新數
used[x]=0;//回溯,以免影響之後的dfs
return 0;
}
int main()
{
read(n);
t=1<<n;
printf("%d ",t);
eular(t-2,1);//從每位走n位子串,可得到的完整子串數量為2^n-2
for (int i=1;i<=t;++i)
printf("%d",ans[i]);
return 0;
}
邱神現場A題:
#include<bits/stdc++.h>
using namespace std;
int read()
{
int a;
cin>>a;
return a;
}
int i,k,m;
struct node
{
int x,deep;
}o[10010];
bool Orz(node a,node b)
{
return a.deep<b.deep;
}
void dfs(int now,int deep)
{
if(deep==m+1)
{
now=now%(m/2);
now=now*2;
if(now)
return ;
sort(o,o+m,Orz);
for(i=1;i<k;i++)
cout<<0;
for(i=0;i<=m-k;i++)
cout<<o[i].x%2;
exit(0) ;
}
//這裡應該有一個關於deep和now的if使得dfs停下來並輸出
now=now%(m/2);
now=now*2;
if(!o[now].deep)
{
o[now].deep=deep;
dfs(now,deep+1);
o[now].deep=0;
}
now++;
if(!o[now].deep)
{
o[now].deep=deep;
dfs(now,deep+1);
o[now].deep=0;
}
return ;
}
int main()
{
//freopen("123.in","r",stdin);
k=read();m=int(pow(2,k*1.0));
cout<<m<<' ';
for(i=0;i<m;i++)
o[i].x=i;
o[0].deep=1;
dfs(0,2);
}
B. POJ 1386 Play on Words
題目
題解
其實就是讓判斷是否是尤拉回路或尤拉通路.
建圖需要一點思維,把26個字母當成是節點,每個單詞當成是一條有向邊。
比如單詞就是一條到的有向邊。
然後用並查集判斷圖是否聯通即可。
程式碼
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
const int maxn=30;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int fa[maxn];
inline int get(int x)
{
if (x==fa[x]) return x;
return fa[x]=get(fa[x]);
}
int indeg[maxn],outdeg[maxn];
int main()
{
int t;read(t);
while (t--)
{
int n;read(n);
memset(indeg,0,sizeof(indeg));
memset(outdeg,0,sizeof(outdeg));
for (int i=0;i<26;++i)
fa[i]=i;
char str[1005];
for (int i=1;i<=n;++i)
{
scanf("%s",str);
int x=str[0]-'a';
int y=str[strlen(str)-1]-'a';
if (get(x)!=get(y))
fa[get(x)]=get(y);
++indeg[y],++outdeg[x];
}
bool flag=true;
int cnt=0,In=0,Out=0;
for (int i=0;i<26;++i)
{
if (get(i)==i && (indeg[i]+outdeg[i])>0)
++cnt;
if (indeg[i]!=outdeg[i])
{
if (indeg[i]-1==outdeg[i])
++In;
else if (indeg[i]+1==outdeg[i])
++Out;
else
flag=false;
}
}
if (flag && cnt==1 && (In==1 && Out==1 || In==0 && Out==0))
puts("Ordering is possible.");//尤拉回路和通路都符合題目條件
else
puts("The door cannot be opened.");
}
return 0;
}
C. CF 516B. Drazil and Tiles
題目
程式碼
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+2;
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};
const char ch[]="><v^";
const char str[]="<>^v";
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
struct rec
{
int x,y;
}a[maxn*maxn];
int m,n,tot,G[maxn][maxn];
char c[maxn][maxn];
inline bool check(int x,int y)
{
return x>0 && x<=m && y>0 && y<=n;
}
inline void dfs(int x,int y)
{
int cnt=0;
for (int i=0;i<4;++i)
{
int xx=x+dx[i],yy=y+dy[i];
if (check(xx,yy) && c[xx][yy]=='.') ++cnt;
}
G[x][y]=cnt;
}
inline bool topsort()
{
queue<pair<int,int> >q;
int cnt=0;
for (int i=0;i<tot;++i)
{
int x=a[i].x,y=a[i].y;
if (G[x][y]==1)
{
q.push(pair<int,int> (x,y));
G[x][y]=0;
}
}
pair<int,int>m;
while (!q.empty())
{
m=q.front();
q.pop();
int x=m.first,y=m.second;
--G[x][y];
for (int i=0;i<4;++i)
{
int xx=x+dx[i],yy=y+dy[i];
if (check(xx,yy) && c[xx][yy]=='.')
{
G[xx][yy]=0;
c[xx][yy]=ch[i];
c[x][y]=str[i];
for (int j=0;j<4;++j)
{
int xxx=xx+dx[j],yyy=yy+dy[j];
if (check(xxx,yyy) && c[xxx][yyy]=='.')
{
dfs(xxx,yyy);
if (G[xxx][yyy]==1)
q.push(pair<int,int> (xxx,yyy));
}
}
cnt+=2;
}
}
}
return cnt==tot;
}
int main()
{
read(m);read(n);tot=0;
for (int i=1;i<=m;++i)
{
scanf("%s",c[i]+1);
for (int j=1;j<=n;++j)
if (c[i][j]=='.')
{
a[tot].x=i,a[tot++].y=j;
G[i][j]=0;
if (check(i-1,j) && c[i-1][j]=='.')
++G[i-1][j],++G[i][j];
if (check(i,j-1) && c[i][j-1]=='.')
++G[i][j-1],++G[i][j];
}
}
if (topsort())
for (int i=1;i<=m;++i)
printf("%s\n",c[i]+1);
else
puts("Not unique");
return 0;
}
D. POJ 3169 Layout
題目
程式碼
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
const int maxn=1e6+10;
const int inf=0x3f3f3f3f;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxn*2],edge[maxn*2],Next[maxn*2],head[maxn],len=0;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int dist[maxn],cnt[maxn],vis[maxn];
inline int spfa(int s,int n)
{
for (int i=0;i<maxn;++i) dist[i]=inf;
memset(cnt,0,sizeof(cnt));
memset(vis,0,sizeof(vis));
queue<int>q;
dist[s]=0,vis[s]=1;
q.push(s),++cnt[s];
while (!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (dist[y]>dist[x]+z)
{
dist[y]=dist[x]+z;
if (!vis[y])
{
vis[y]=1,q.push(y);
if (++cnt[y]>n) return -1;//存在負環
}
}
}
}
if (dist[n]==inf) return -2;
return dist[n];
}
int main()
{
int n,x,y;
read(n);read(x);read(y);
for (int i=1;i<n;++i)
add(i+1,i,0);
for (int i=1;i<=x;++i)
{
int a,b,d;
read(a);read(b);read(d);
add(a,b,d);
}
for (int i=1;i<=y;++i)
{
int a,b,d;
read(a);read(b);read(d);
add(b,a,-d);
}
printf("%d\n",spfa(1,n));
return 0;
}
E. POJ 2983 Is the Information Reliable?
題目
題解
程式碼
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
typedef long long ll;
const int maxm=1e5+10,maxn=1010;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxm<<1],Next[maxm<<1],head[maxn],len;
ll edge[maxm<<1];
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
ll dist[maxn];
int n,m,vis[maxn],cnt[maxn];
inline bool spfa(int s)
{
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
queue<int>q;
dist[s]=0,vis[s]=1;
q.push(s);
while (!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (dist[y]>dist[x]+z)
{
dist[y]=dist[x]+z;
if (!vis[y])
{
q.push(y),vis[y]=1;
if (++cnt[y]>n) return false;
}
}
}
}
return true;
}
int main()
{
while (~scanf("%d %d",&n,&m))
{
memset(head,0,sizeof(head));
len=0;
char s[5];int x,y;ll z;
for (int i=1;i<=m;++i)
{
scanf("%s",s);
if (s[0]=='P')
{
read(x);read(y);read(z);
add(x,y,-z);add(y,x,z);
}
else
{
read(x);read(y);
add(x,y,-1);//x1-x2>=1,轉化為約束條件為x2-x1<=-1
}
}
for (int i=1;i<=n;++i)
add(0,i,0);//新增源點到其他頂點的邊,權值為0
if (!spfa(0))
puts("Unreliable");
else
puts("Reliable");
}
return 0;
}
F. HDU 3440 House Man
題目
題解
1.兩個相鄰點之間最小距離為一,則有,等價於;
2.高度最接近的兩個點的最大距離為m,按距離排序之後可有;
這樣,差分約束系統的條件找出來了;
剩下就是構圖的事了。
由的的編輯條件可知,我們給各個點制定了一個方向,就是從左到右是依次增大的。
這就限定了的的連邊條件,必須是由對應的序號小的點連向序號大的點,否則,就把他們一下就好了。
程式碼
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
struct orz
{
int id,height;
}a[maxn];
int ver[maxn<<4],edge[maxn<<4],Next[maxn<<4],head[maxn],len;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
inline bool cmp(orz a,orz b)
{
return a.height<b.height;
}
int dist[maxn],vis[maxn],cnt[maxn];
inline int spfa(int s,int e,int n)
{
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
queue<int>q;
dist[s]=0,vis[s]=1;
q.push(s);
while (!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
if (++cnt[x]>n) return -1;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (dist[y]>dist[x]+z)
{
dist[y]=dist[x]+z;
if (!vis[y]) q.push(y),vis[y]=1;
}
}
}
return dist[e];
}
int main()
{
int t;read(t);
for (int cas=1;cas<=t;++cas)
{
memset(head,0,sizeof(head));//初始化
len=0;
int n,D;
read(n);read(D);
for (int i=1;i<=n;++i)
{
read(a[i].height),a[i].id=i;
if (i!=n)
add(i+1,i,-1);
}
sort(a+1,a+n+1,cmp);
for (int i=1;i<n;++i)
{
int x=a[i].id,y=a[i+1].id;
if (x>y)
swap(x,y);
add(x,y,D);
}
int s=a[1].id,e=a[n].id;
if (s>e)
swap(s,e);
printf("Case %d: %d\n",cas,spfa(s,e,n));
}
return 0;
}
G. POJ 1275 Cashier Employment
題目
題解
設 為來應聘的在第i個小時開始工作的人數
為第i個小時至少需要的人數
為招到的在第i個小時開始工作的人數
根據題意有:
再設
則有:
還需要新增一個隱藏不等式:
通過列舉,來檢測是否滿足條件,題目是求最小值,即求最長路,以0為源點。
最後,其實是不用寫二分的,寫一個手寫佇列,跑的比二分都快!
程式碼
/***************************************************************************
Result Memory Time Language Code Length Submit Time
Accepted 100K 16MS C++ 2219B 2019-02-26 21:33:34
****************************************************************************/
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
const int maxn=30,inf=0x7fffffff;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxn*30],edge[maxn*30],Next[maxn*30],head[maxn],len;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int dist[maxn],cnt[maxn],q[maxn*30];
bool vis[maxn];
inline bool spfa(int ans)
{
int hd=0,tl=1;//即head,tail
for (int i=0;i<=24;++i)
dist[i]=-inf,vis[i]=cnt[i]=0;
dist[0]=0,vis[0]=1;
q[0]=0;//手寫佇列
while (hd<tl)
{
int x=q[hd];
++hd;
vis[x]=0;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (dist[y]<dist[x]+z)
{
dist[y]=dist[x]+z;
if (!vis[y]) q[tl]=y,++tl,vis[y]=1;
if (++cnt[y]>24) return 0;
}
}
}
if (dist[24]==ans)
return 1;
return 0;
}
int num[maxn];//num[i]標示i時刻開始工作的人
int r[maxn];//r[i]標示i時刻至少需要多少人
inline void build(int ans)//建圖這也是本題目的關鍵,建模
{
for (int i=0;i<=24;++i)
head[i]=0;
len=0;
add(0,24,ans);
for (int i=1;i<=24;++i)
add(i-1,i,0),add(i,i-1,-num[i]);
for (int i=1;i<=8;++i)
add(i+16,i,r[i]-ans);
for (int i=9;i<=24;++i)
add(i-8,i,r[i]);
}
int main()
{
int t;read(t);
while (t--)
{
bool flag=0;
for (int i=1;i<=24;++i)
read(r[i]),num[i]=0;
int n;read(n);
for (int i=1;i<=n;++i)
{
int tim;read(tim);
++num[tim+1];
}
for (int i=0;i<=n;++i)
{
build(i);
if (spfa(i))
{
flag=1;
printf("%d\n",i);
break;
}
}
if (!flag)
puts("No Solution");
}
return 0;
}
相關文章
- 差分約束
- 拓撲排序排序
- 拓撲排序,YYDS排序
- 拓撲排序模板排序
- 拓撲排序小結排序
- 圖論——拓撲排序圖論排序
- 筆記:拓撲排序筆記排序
- 淺談差分約束系統
- 差分約束系統詳解
- 差分約束學習筆記筆記
- 圖(3)--拓撲排序與關鍵路徑排序
- Reward (圖論+拓撲排序)圖論排序
- 拓撲排序 - Topological Sort排序
- 拓撲排序核心程式碼排序
- HDU 4857 逃生(拓撲排序)排序
- 【筆記/模板】拓撲排序筆記排序
- AOV網與拓撲排序排序
- DFS實現拓撲排序排序
- 差分約束的一些理解
- VOL.2 拓撲排序與關鍵路徑排序
- 拓撲排序就這麼回事排序
- HDU4857逃生(拓撲排序)排序
- 紙上談兵: 拓撲排序排序
- poj 1094 拓撲排序排序
- 拓撲排序詳解(梅開二度之dfs版按字典序輸出拓撲路徑+dfs版輸出全部拓撲路徑排序
- POJ 2983-Is the Information Reliable?(差分約束系統)ORM
- POJ 1364-King(差分約束系統)
- [演算法學習筆記] 差分約束演算法筆記
- 有向圖的拓撲排序——DFS排序
- poj1094 拓撲排序排序
- 演算法-圖論-拓撲排序演算法圖論排序
- 網路拓撲圖:網路拓撲圖介紹及線上製作
- 網路拓撲結構
- 演算法學習之路|差分約束系統演算法
- 差分約束系統+poj1201
- 圖解拓撲排序+程式碼實現圖解排序
- 【圖論】拓撲排序+優先佇列圖論排序佇列
- POJ 3249-Test for Job(拓撲排序&&DP)排序