g_1

第一道:限制了路径上的两两点权差之间都要小于等于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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值