Description

 史努比最爱水题了,他知道现在他要挑战的是一道超级大水题哦。不过因为太水了,而且他又很懒,所以把这道水题推给了你们。

 

有n个(不包括ZSTU和火车东站)车站介于ZSTU和火车东站之间,一共有m辆公交车往返于这些车站和火车东站。每个车站假设可以站无数个人,每辆车最多承载H[i]个人,经过S[i]个车站。假设一辆车依次经过1,2,3,这三个车站,那么它将一直往复1->2->3->1->2...现在认为车从一个站到下一个站要花费1个小时,人只能在车站或ZSTU,火车东站上下车,初始时有k个人在ZSTU(0站),所有的车都在初始站(所给车站的第一个车站为初始站),现在问你们最快让全部人从ZSTU到火车东站要多少小时。所有车同时运行。

 

Input

 第一行有一个T<=10,表示T组测试样例,第二行三个数n(车站数目),m(车数目),k(人数),(n<=13,m<=20,k<=50);接下来的m行给出车信息,每行给出H[i](能承载的最大人数),S[i](经过的车站数目),还有依次给出S[i]个车站编号。ZSTU用0编号表示,火车东站用-1表示。

 

Output

 若无解则输出-1,否则逐行输出答案。

 

Sample Input

2 2 2 1 1 3 0 1 2 1 3 1 2 -1 2 3 3 1 2 0 2 1 2 1 2 1 2 1 -1

Sample Output

5 7

HINT

 

 第一个样例,一人从0站乘坐1号公交车途径1站,到2站下车,花费2S;此时2号车位于-1站,再经过2S,2号车从-1站途径1站到2站,人上2号车再经过1S到达-1站,共花费5S。或者一人从0站乘坐一号公交车到1站下车,花费1S,此时2号车位于2站,再经过2S到1站,人上2号车再经过2S到达-1站,共花费5S。

 

题解:

首先判断学校到火车东站能不能到站,即是否在同一个集团里面,用并查集就可以了。然后跑网络流,网络流跑一次后会更改原来储存的边的信息,因此可以枚举时间进行网络流,按照时间建边,在上一个时间段跑网络流的基础上,继续建图在继续跑网络流,将每次的最大流加起来直到总和大于等于k就可以返回当前天数了。

具体操作是将第i-1小时的第j个车的信息向第i小时的第j个车进行连边,容量为INF,将每辆车第i-1小时所待的公交车站向第i小时所待的公交车站连边,容量为车的最大载人数。

#include <bits/stdc++.h>
//CLOCKS_PER_SEC
#define se second
#define fi first
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define Pii pair<int,int>
#define Pli pair<ll,int>
#define ull unsigned long long
#define pb push_back
#define fio ios::sync_with_stdio(false);cin.tie(0)
const double Pi=3.14159265;
const int N=1e3+5;
const ull base=163;
const int INF=0x3f3f3f3f;
using namespace std;
int n,m,k,s,t;
int head[10100],to[100010],cur[10100],nx[100010];
int cap[100010];
int tot=0;
void add(int x,int y,int c){
    to[tot]=y;
    nx[tot]=head[x];
    cap[tot]=c;
    head[x]=tot++;
    
    to[tot]=x;
    nx[tot]=head[y];
    cap[tot]=0;
    head[y]=tot++;
}
void init(int n){
    tot=0;
    memset(head,-1,sizeof(head));
}
int d[N];
int bfs(){
    memset(d,-1,sizeof(d));
    queue<int>q;
    q.push(s);
    d[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];~i;i=nx[i]){
            int v=to[i];
            if(d[v]==-1&&cap[i]>0){
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    return d[t]!=-1;
}
int dfs(int s,int a){
    if(s==t||a==0)return a;
    int flow=0,f;
    for(int &i=cur[s];~i;i=nx[i]){
        int v=to[i];
        if(d[s]+1==d[v] && cap[i]>0 && (f=dfs(v,min(a,cap[i])))>0){
            flow+=f;
            cap[i]-=f;
            cap[i^1]+=f;
            a-=f;
            if(a==0)break;
        }
    }
    return flow;
}
int dinic(){
    int ans=0;
    while(bfs()){
        for(int i=0;i<=1000;i++)cur[i]=head[i];
        while(int di=dfs(s,INF)){
            ans+=di;
        }
    }
    return ans;
}
int ship[N][N];
int num[N];
int r[N];
int fa[N];
int F(int x){
    return fa[x]==x?x:fa[x]=F(fa[x]);
}

bool check(int x,int y){
    if(F(x)==F(y))return 1;
    else return 0;
}
int cal(int a,int d){
    return d*n+a;
}
void solve(){
    int flow=0;
    int i;
    init(n);// n -1     n-1   0
    add(s,cal(n-1,0),INF);
    add(cal(n,0),t,INF);
    for(i=1;flow<k;i++){
        add(s,cal(n-1,i),INF);add(cal(n,i),t,INF);
        for(int j=1;j<=n;j++){
            add(cal(j,i-1),cal(j,i),INF);
        }
        for(int j=1;j<=m;j++){
            int a=(i-1)%num[j]+1;
            int b=i%num[j]+1;
            add(cal(ship[j][a],i-1),cal(ship[j][b],i),r[j]);
        }
        flow+=dinic();
        
    }
   printf("%d\n",i-1);
}
int main(){
	 // clock_t start, end;
    int T;scanf("%d",&T);
    while(T--){
        s=0,t=1000;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<=n+2;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&r[i],&num[i]);
            for(int j=1;j<=num[i];j++){
                scanf("%d",&ship[i][j]);
                if(ship[i][j]==0)ship[i][j]=n+1;
                if(ship[i][j]==-1)ship[i][j]=n+2;
                if(j>1){
                    fa[F(ship[i][j-1])]=F(ship[i][j]);
                }
            }
        }
        n+=2;
        if(check(n, n-1)){
            solve();
        }
        else{
            printf("0\n");
        }
    }
    // end = clock();
    // cout << "time :"<<(double)(end - start) / CLOCKS_PER_SEC << endl;
    return 0;
}
/*

*/