第一道:限制了路径上的两两点权差之间都要小于等于m,数据小,枚举区间即可
第二道:给n种插座,m个设备对应的插座,还有k个适配器可以转换插座,适配器可以嵌套…求m-匹配数,传递闭包加二分图..
第三道:n个字符,给m个含’<’的式子,问第几步可以判断他们的关系,可以判断直接结束程序。拓扑排序…有点坑
//POJ 1062 dijk
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#define mp make_pair
#define X first
#define Y second
#define sz(s) (int)E[s].size()
using namespace std;
typedef long long LL;
const int maxn = 100 + 5;
int m, n;
struct x {
int lv, price;
} a[maxn], tp[maxn];
vector<pair<int, int> >E[maxn], tmp[maxn];
int dis[maxn], vis[maxn];
void init() {
for(int i = 0; i <= n; i++) {
E[i].clear();
tmp[i].clear();
}
}
int dijk(int S) {
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i++)
dis[i] = 1e7;
dis[S] = 0;
while(1) {
int s = -1, mn = 1e8;
for(int i = 1; i <= n; i++) {
if(!vis[i] && dis[i] < mn ) {
mn = dis[i];
s = i;
}
}
if(s == -1) break;
vis[s] = 1;
for(int i = 0; i < sz(s); i++) {
pair<int, int> v = E[s][i];
if(dis[v.X] > dis[s] + v.Y) {
dis[v.X] = dis[s] + v.Y;
}
}
}
int ans = 1e8;
for(int i = 1; i <= n; i++)
ans = min(ans, dis[i] + a[i].price);
return ans;
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCaL
/**
求最短路,但是要路径上的任意两个点的等级lv的差值都<=m
枚举lv所能在的区间[LV - m + i, LV +i],只要点属于这个区间,就加入图。
对每个图求一次最短路
**/
while(cin >> m >> n) {
init();
int len = 1, t;
for(int i = 1; i <= n; i++) {
cin >> a[i].price >> a[i].lv >> t;
for(int j = 0; j < t; j++) {
int v, w;
cin >> v >> w;
tmp[i].push_back(mp(v, w));
}
}
int ans = 1e8;
for(int k = 0; k <= m; k++) {
int L = a[1].lv - m + k , R = a[1].lv + k;
for(int i = 1; i <= n; i++) {
if(a[i].lv >= L && a[i].lv <= R)
for(int j = 0; j < (int)tmp[i].size(); j++) {
pair<int, int> v = tmp[i][j];
if(a[v.X].lv >= L && a[v.X].lv <= R)
E[i].push_back(v);
}
}
ans = min(ans,dijk(1));
for(int i=1;i<=n;i++)E[i].clear();
}
cout<<ans<<endl;
}
return 0;
}
//POJ 1087 二分图,可以网络流,不会-_-
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <cstring>
#define mp make_pair
#define X first
#define Y second
#define sz(s) (int)E2[s].size()
using namespace std;
typedef long long LL;
int n, m, k, tot = 1;
map<string, int>M;
bool E[506][505], vis[506], vis2[506];
vector<int>E2[505];
string s1[106], s2[106][2], s3[106][2];
void dfs(int s, int p) {
vis2[s] = 1;
if(vis[s]/*vis不是vis2*/) E[s][p] = 1;
for(int i = 0; i < sz(s); i++) {
if(!vis2[E2[s][i]]){
dfs(E2[s][i], p);
}
}
}
bool used[505];
int linker[505], uN, vN;
bool bin(int u) {
for(int v = vN + 1; v <= tot; v++) {
if(E[u][v] && !used[v]) {
used[v] = 1;
if(linker[v] == -1 || bin(linker[v])) {
linker[v] = u;
return true;
}
}
}
return false;
}
int hungary() {
int res = 0;
memset(linker, -1, sizeof linker);
for(int u = 1; u <= uN; u++) {
memset(used, 0, sizeof used);
if(bin(u)) res++;
}
return res;
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCaL
/**
点集T1和T2,T1是已有的插座
先将字符串映射成整数
k:适配器建边成有向图G
m:对T2的每个点u都连上T1中以v为起点的可达的所有点 建立新图K
对图K做一个二分图匹配
vis为1则是T1中的点
**/
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
cin >> s1[i];
M[s1[i]] = tot;
vis[tot++] = 1;//可选的点
}
uN = tot - 1;
cin >> m;
for(int j = 1; j <= m; j++) {
cin >> s2[j][0] >> s2[j][1];
if(!M[s2[j][1]])
M[s2[j][1]] = tot++;
}
vN = tot - 1;//1---uN是可选的点,uN+1 --- vN是不可选的点,但也是插座,vN+1 --- tot是设备
cin >> k;
for(int i = 1; i <= k; i++) {
cin >> s3[i][0] >> s3[i][1];
int f = M[s3[i][0]], s = M[s3[i][1]];
if(!f) f = M[s3[i][0]] = tot++;//狂wa漏了这两句if 如果T没出现过而A出现过,假如有T -> A,C->T,那就可以转成C->A了
if(!s) s = M[s3[i][1]] = tot++;
E2[f].push_back(s);//适配器的有向图
}
for(int j = 1; j <= m; j++) {
M[s2[j][0]] = tot;
int u = tot, v = M[s2[j][1]];
memset(vis2, 0, sizeof vis2);
dfs(v, u);
tot++;
}
tot--;
/*for(int i = 1; i <= n; i++)
cout << s1[i] << " " << M[s1[i]] << endl;
for(int i = 1; i <= m; i++)
cout << s2[i][0] << " " << s2[i][1] << " " << M[s2[i][0]] << " " << M[s2[i][1]] << endl;
for(int i = 1; i <= k; i++)
cout << s3[i][0] << " " << s3[i][1] << " " << M[s3[i][0]] << " " << M[s3[i][1]] << endl;
for(int i = 1; i <= tot; i++) {
for(int j = 1; j <= tot; j++) {
if(E[i][j]) {
printf("%d %d\n", i, j);
}
}
}*/
cout << m - hungary() << endl;
return 0;
}
//拓扑排序
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#define mp make_pair
#define X first
#define Y second
#define sz(s) (int)E[s].size()
using namespace std;
typedef long long LL;
const int maxn = 1000 + 5;
int m, n;
int E[30][30];
int in[30], tin[30];
int ans[30];
void init() {
memset(in, 0, sizeof in);
memset(E, 0, sizeof E);
}
int topoSort() {
int fg = 0;
for(int i = 1; i <= n; i++)
tin[i] = in[i];
int len = 1;
for(int i = 1; i <= n; i++) {
int cnt = 0, val = -1;
for(int j = 1; j <= n; j++)
if(tin[j] == 0)
cnt++, val = j;
if(!cnt) return -1;
if(cnt > 1) fg = 1;//不能直接return 1,因为会漏掉环例如4 3 A<C B<A C<A
ans[len++] = val;
tin[val] = -1;
for(int j = 1; j <= n; j++)
if(E[val][j]) tin[j]--;
}
return fg;
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCaL
/**
对每一次读入都进行一次拓扑排序,出现环直接return ,不能确定关系的时候也要for完才行,才能检查图中的是否有环
**/
while(cin >> n >> m,n||m) {
init();
string s;
bool flag = 0;
for(int i = 0; i < m; i++) {
cin >> s;
int u = 1 + s[0] - 'A', v = 1 + s[2] - 'A';
if(!E[u][v]) in[v]++;
E[u][v] = 1;
if(!flag) {
int d = topoSort();
if(d == 0) {
printf("Sorted sequence determined after %d relations: ", i + 1);
for(int i = 1; i <= n; i++)
printf("%c", ans[i] + 'A' - 1);
printf(".\n");
flag = 1;
} else if(d == -1) {
printf("Inconsistency found after %d relations.\n", i + 1);
flag = 1;
}
}
}
if(!flag)
puts("Sorted sequence cannot be determined. ");
}
return 0;
}