hdu 4598 Difference
一开始没看题目中的<=> 符号,各种错误。实际上可化简为典型的判断差分约束有无解的问题,需要用到SPFA。#include<cstdio> #include<algorithm> #include<vector> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int MAXN = 305; int n, res, TT = 1000; int mmp[MAXN]; char str[MAXN][MAXN]; struct node{int v; int w;}; vector<node> head[MAXN]; void dfs(int u, int c) { if (!res) return; mmp[u] = c; for (int i = 0, len = head[u].size(); i< len; ++i) { int v = head[u][i].v; if (mmp[v] != 0) { if (mmp[v] + c != 0) { res = 0; return; } } else { dfs(v, 0-c); } } } int qq[MAXN*MAXN], bg, ed, vis[MAXN], dis[MAXN], cnt[MAXN]; int spfa() { int st = n; bg = ed = 0; for (int i = 0; i< n; ++i) vis[i]=0, dis[i]=TT*TT, cnt[i]=0; vis[st] = 1; dis[st] = 0; qq[ed++] = st; cnt[st]++; while (bg < ed) { int u = qq[bg++]; vis[u] = 0; for (int i = 0, len = head[u].size(), v; i< len; ++i) { v=head[u][i].v; if (dis[u]+head[u][i].w < dis[v]) { dis[v] = dis[u]+head[u][i].w; if (!vis[v]) { vis[v] = 1; qq[ed++] = v; cnt[v]++; if (cnt[v] > n) return 0; } } } } return 1; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 0; i< n; ++i) { scanf("%s", str[i]); head[i].clear(); node tp; for (int j = 0; j< n; ++j) { if (str[i][j] == '1') tp.v = j, head[i].push_back(tp); } } memset(mmp, 0, sizeof mmp); res = 1; for (int i = 0; i< n; ++i) { if (!mmp[i]) dfs(i, 1); } if(res == 1) { node tp; for (int i = 0; i<= n; ++i) head[i].clear(); for (int i = 0; i< n; ++i) { for (int j = 1+i; j< n; ++j) { if (str[i][j] == '0') { if (mmp[i] == 1) { tp.v = i; tp.w = TT-1; head[j].push_back(tp); //printf("%d %d %d\n", j, tp.v, tp.w); } else { tp.v = j; tp.w = TT-1; head[i].push_back(tp); //printf("%d %d %d\n", i, tp.v, tp.w); } } else { if (mmp[i] == 1) // positive { tp.v = j; tp.w = -TT; head[i].push_back(tp); //printf("%d %d %d\n", i, tp.v, tp.w); } else { tp.v = i; tp.w = -TT; head[j].push_back(tp); //printf("%d %d %d\n", j, tp.v, tp.w); } } } } for (int i = 0; i< n; ++i) { tp.v = i; tp.w = 0; head[n].push_back(tp); } if (spfa()) puts("Yes"); else puts("No"); } else puts("No"); } return 0; }
hdu 3592 World Exhibition
典型的差分约束,需要注意的是因为涉及到求点之间距离,所以无需添加一个源点使其与所有定点相连且边权均为0。#include<cstdio> #include<algorithm> #include<vector> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int MAXN = 1005; const int INF = 1<<30; struct eg{int v, w;}; vector<eg> e[MAXN]; int n, vis[MAXN], dis[MAXN], cnt[MAXN]; int q[MAXN*MAXN], bg, ed; int spfa() { bg = ed = 0; int st = 1; for (int i = 0; i<= n; ++i) vis[i]=0, dis[i]=INF, cnt[i]=0; vis[st] = 1, dis[st] = 0, cnt[st]++, q[ed++]=st; while (bg < ed) { int u = q[bg++]; vis[u] = 0; for (int i = 0, len = e[u].size(), v; i< len; ++i) { v = e[u][i].v; if (dis[v] > dis[u] + e[u][i].w) { dis[v] = dis[u] + e[u][i].w; if (!vis[v]) { vis[v] = 1; q[ed++] = v; cnt[v]++; if (cnt[v] > n) return -1; } } } } if(dis[n] == INF) return -2; return dis[n]; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); while (t--) { int x, y; eg tp; scanf("%d%d%d", &n, &x, &y); for (int i = 1; i<= n; ++i) { e[i].clear(); if ( i > 1) tp.v = i-1, tp.w = 0, e[i].push_back(tp); } for (int i= 0; i< x; ++i) { int a, b, c; scanf("%d%d%d", &a, &b, &c); tp.v = b; tp.w = c; e[a].push_back(tp); } for (int i = 0; i< y; ++i) { int a, b, c; scanf("%d%d%d", &a, &b, &c); tp.v = a; tp.w = -c; e[b].push_back(tp); } printf("%d\n", spfa()); } return 0; }
hdu 1534 Schedule Problem
没什么好说的,需要加个源点#include<cstdio> #include<algorithm> #include<vector> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int MAXN = 100005; const int INF = 1<<30; struct eg{int v, w;}; vector<eg> e[MAXN]; int n, vis[MAXN], dis[MAXN], cnt[MAXN], last[MAXN]; int q[MAXN*10], bg, ed; int spfa() { bg = ed = 0; int st = 0; for (int i = 0; i<= 2*n; ++i) vis[i]=0, dis[i]=INF, cnt[i]=0; vis[st] = 1, dis[st] = 0, cnt[st]++, q[ed++]=st; while (bg < ed) { int u = q[bg++]; vis[u] = 0; for (int i = 0, len = e[u].size(), v; i< len; ++i) { v = e[u][i].v; if (dis[v] > dis[u] + e[u][i].w) { dis[v] = dis[u] + e[u][i].w; if (!vis[v]) { vis[v] = 1; q[ed++] = v; cnt[v]++; if (cnt[v] > 2*n) return 0; } } } } return 1; } char ss[20]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int cs = 1; while (scanf("%d", &n) && n != 0) { eg tp; if (cs != 1) puts(""); printf("Case %d:\n", cs++); for (int i = 0; i<= 2*n; ++i) e[i].clear(); for (int i = 1; i<= n; ++i) { int tt; scanf("%d", &tt); last[i] = tt; tp.v = 2*i-1; tp.w = -tt; e[2*i].push_back(tp); tp.v = 2*i; tp.w = tt; e[2*i-1].push_back(tp); tp.v = 2*i; tp.w = 0; e[0].push_back(tp); tp.v = 2*i-1; e[0].push_back(tp); } while(1) { scanf("%s", ss); if (strcmp(ss, "#") == 0) break; int a, b; scanf("%d%d", &a, &b); if (strcmp(ss, "FAS") == 0) { tp.v = 2*b-1; tp.w = 0; e[2*a].push_back(tp); } else if ( strcmp(ss, "FAF") == 0) { tp.v = 2*b; tp.w = 0; e[2*a].push_back(tp); } else if (strcmp(ss, "SAF") == 0) { tp.v = 2*b; tp.w = 0; e[2*a-1].push_back(tp); } else // SAS { tp.v = 2*b-1; tp.w = 0; e[2*a-1].push_back(tp); } } if (!spfa()) puts("impossible"); else { int k = 0, mm = INF; for (int i =1; i<= 2*n; ++i) { if (dis[i] == INF) { puts("impossible"); k = 1; break; } if (i & 1) { if (dis[i] < mm) mm = dis[i]; } } if (!k) { for (int i = 1, j=1; i<= 2*n; i+=2,++j) { printf("%d %d\n", j, dis[i]-mm); } } } } return 0; }
hdu 1529 Cashier Employment
差分约束的核心是找出所有符合条件的变量两两之间的关系。算是好题,如何把多元关系式转化为二元不等式废了不少功夫#include<cstdio> #include<algorithm> #include<vector> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int MAXN = 50; const int INF = 1<<30; struct eg{int v, w;}; vector<eg> e[MAXN]; int n, vis[MAXN], dis[MAXN], cnt[MAXN]; int q[10000], bg, ed; int ready[MAXN], need[MAXN]; int spfa(int num) { for (int i = 0; i<= 7; ++i) { eg tp; tp.v = i+16; tp.w = num-need[i]; e[i].push_back(tp); } bg = ed = 0; int st = 24; for (int i = 0; i<= 30; ++i) vis[i]=0, dis[i]=INF, cnt[i]=0; vis[st] = 1, dis[st] = 0, cnt[st]++, q[ed++]=st; while (bg < ed) { int u = q[bg++]; vis[u] = 0; for (int i = 0, len = e[u].size(), v; i< len; ++i) { v = e[u][i].v; if (dis[v] > dis[u] + e[u][i].w) { dis[v] = dis[u] + e[u][i].w; if (!vis[v]) { vis[v] = 1; q[ed++] = v; cnt[v]++; if (cnt[v] > 25) return 0; } } } } return 1; } void build() { eg tp; for (int i = 0; i < 30; ++i) e[i].clear(); for (int i = 1; i < 24; ++i) { tp.v = i-1; tp.w = 0; e[i].push_back(tp); } for (int i= 1; i< 24; ++i) { tp.v = i; tp.w = ready[i]; e[i-1].push_back(tp); } for (int i = 8; i< 24; ++i) { tp.v = i-8; tp.w = -need[i]; e[i].push_back(tp); } for (int i = 0; i< 24; ++i) { tp.v = i; tp.w = 0; e[24].push_back(tp); } } void bnry_sch() { int high, low, mid, res = -1; high = n; low = 0; while ( low < high) { mid = (low+high)/2; if (spfa(mid)) { res = mid; high = mid; } else low = mid+1; for (int i = 0; i<= 7; ++i) { e[i].pop_back(); } } if (res == -1) puts("No Solution"); else printf("%d\n", res); } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); while (t--) { memset(ready, 0, sizeof ready); for (int i = 0; i < 24; ++i) { scanf("%d", need+i); } scanf("%d", &n); for (int i= 0; i < n; ++i) { int tp; scanf("%d", &tp); ++ready[tp]; } build(); bnry_sch(); } return 0; }
hdu 3666 THE MATRIX PROBLEM
对时间卡的比较严(用到dfs的spfa),加入源点然后判断是否有解。
L <= Cij * Ai / Bj<= U
L/Cij <= Ai / Bj<= U/Cij
L' <= Ai / Bj<= U'
log(L') <= log(Ai / Bj)<= log(U')
#include<cstdio> #include<algorithm> #include<vector> #include<cmath> #include<queue> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int MAXN = 810; struct node { int v, next; double w; }ee[MAXN*MAXN]; int head[MAXN], ne; int n, m; double dis[MAXN], L, U; bool vis[MAXN], instk[MAXN]; void add(int u, int v, double w) { ee[ne].v = v; ee[ne].w = w; ee[ne].next = head[u]; head[u] = ne++; } bool spfa(int u) { if (instk[u]) return 0; instk[u] = 1; vis[u] = 1; for (int i=head[u]; ~i; i=ee[i].next) { int v = ee[i].v; if (dis[v] > dis[u]+ee[i].w) { dis[v] = dis[u]+ee[i].w; if (!spfa(v)) return false; } } instk[u] = 0; return 1; } bool judge() { memset(vis, 0, sizeof vis); memset(instk, 0, sizeof instk); for (int i = 0; i<= n+m; ++i) { dis[i] = 0; } for (int i = 1; i<= n+m; ++i) { if (!vis[i]) { if (!spfa(i)) return 0; } } return 1; } /* L <= Cij * Ai / Bj<= U L/Cij <= Ai / Bj<= U/Cij L' <= Ai / Bj<= U' log(L') <= log(Ai / Bj)<= log(U') */ double da[405][405]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif while (scanf("%d%d%lf%lf", &n, &m, &L, &U) != EOF) { memset(head, -1, sizeof head); ne = 0; for (int i = 1; i<= n; ++i) { for (int j = 1; j<= m; ++j) { double c, da; scanf("%lf", &da); add(j+n, i, log(U/da)); add(i, j+n, -log(L/da)); } } if (!judge()) puts("NO"); else puts("YES"); } return 0; }